diff --git a/Dockerfile.build b/Dockerfile.build
new file mode 100644
index 0000000..619b1c9
--- /dev/null
+++ b/Dockerfile.build
@@ -0,0 +1,23 @@
+FROM golang:1.9.2
+
+# Install glide
+RUN curl https://glide.sh/get | sh
+
+# Sets the arguments.
+ARG BIN_NAME
+ARG APP_NAME
+ARG WORKDIR=/go/src/bitbucket.org/nemt/${APP_NAME}
+
+# Prepares the work directory.
+RUN mkdir -p ${WORKDIR}
+ADD . ${WORKDIR}
+WORKDIR ${WORKDIR}
+RUN rm -rf glide.lock
+RUN rm -rf vendor/
+
+# Installs dependencies and builds app.
+RUN glide install -force
+RUN go build -o ${BIN_NAME} .
+
+# Pauses the container.
+CMD read
\ No newline at end of file
diff --git a/Dockerfile.run b/Dockerfile.run
new file mode 100644
index 0000000..907af71
--- /dev/null
+++ b/Dockerfile.run
@@ -0,0 +1,22 @@
+FROM amazonlinux
+
+# Sets the arguments.
+ARG BIN_NAME=nemt-portal-api
+ARG APP_NAME=nemt-portal-api
+ARG WORKDIR=/opt/app/
+
+# Creates the necessary directories.
+RUN mkdir -p /opt/app/docs
+RUN mkdir -p /opt/app/static
+RUN mkdir -p /var/log/bsbsi
+
+# Copies the files to the container.
+COPY ./dist/${BIN_NAME} /opt/app/${BIN_NAME}
+ADD ./dist/docs/ /opt/app/docs/
+ADD ./dist/static/ /opt/app/static/
+ADD ./dist/config.toml /opt/app/config.toml
+
+# Sets and executes the app.
+WORKDIR /opt/app
+EXPOSE 5000
+CMD ./nemt-portal-api
diff --git a/Dockerrun.aws.json b/Dockerrun.aws.json
new file mode 100644
index 0000000..ce36d93
--- /dev/null
+++ b/Dockerrun.aws.json
@@ -0,0 +1,12 @@
+{
+ "AWSEBDockerrunVersion": "1",
+ "Image": {
+ "Update": "true"
+ },
+ "Ports": [
+ {
+ "ContainerPort": "5000"
+ }
+ ],
+ "Logging": "/var/log/eb-docker/containers/eb-current-app/stdouterr.log"
+}
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..05b4fb0
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,102 @@
+node {
+ stage("Setting variables") {
+ echo "Setting variables"
+
+ BRANCH_PRD = 'master'
+ BRANCH_STG = 'staging'
+ BRANCH_DEV = 'development'
+
+ // Gets the environment based on the current Git branch.
+ if (env.BRANCH_NAME == BRANCH_PRD) {
+ env.DEPLOY_ENV = 'prd'
+ } else if (env.BRANCH_NAME == BRANCH_STG) {
+ env.DEPLOY_ENV = 'stg'
+ } else if (env.BRANCH_NAME == BRANCH_DEV) {
+ env.DEPLOY_ENV = 'dev'
+ }
+
+ // Define environment variables for other files to use it.
+ env.APP_NAME = "nemt-portal-api"
+ env.ENV_NAME = "${env.APP_NAME}-${env.DEPLOY_ENV}"
+
+ echo "Branch: ${env.BRANCH_NAME}"
+ echo "Environment: ${env.DEPLOY_ENV}"
+
+ echo "Setting variables complete"
+ }
+ stage("Cleaning") {
+ echo "Cleaning"
+
+ sh "rm -rf ${pwd()}/*"
+ deleteDir()
+
+ echo "Cleaning complete"
+ }
+ stage("Build") {
+ echo "Building"
+
+ // Sets package name based on the AWS job name, the current Git tag version and the build ID.
+ GIT_TAG = "\$(git describe --tags --always --dirty)"
+ PKG_NAME = "${GIT_TAG}-${env.JOB_BASE_NAME}-${env.BUILD_ID}"
+ ZIP_FILE_NAME = "${PKG_NAME}.zip"
+
+ // Sets the variables used for Docker login.
+ AWS_DOCKER_ROLE_NAME = "rvbrazil-bsbsi-deploy"
+ AWS_DOCKER_ROLE_ARN = "arn:aws:iam::xxxxxxxxxxx:role/bsbsi-deploy"
+
+ // Downloads repository.
+ echo "Downloading repository"
+ checkout scm
+
+ // Assumes role into our AWS account (for Docker login).
+ sh "aws-assume-role ${AWS_DOCKER_ROLE_ARN} ${AWS_DOCKER_ROLE_NAME}"
+
+ // Uses the AWS CLI to get our Docker login commmand and executes it.
+ sh "\$(aws --region us-east-1 --profile ${AWS_DOCKER_ROLE_NAME} ecr get-login)"
+
+ // Builds the application.
+ sh "make build-${env.DEPLOY_ENV}"
+
+ // Zips the files that will go to S3.
+ sh "cp Dockerfile.run Dockerfile"
+ sh "rm -rf ./*.zip"
+ sh "zip -r ${ZIP_FILE_NAME} dist Dockerfile Dockerrun.aws.json"
+
+ echo "Building complete"
+ }
+ stage("Deploy") {
+ echo "Deploying"
+
+ echo "Environment: ${env.DEPLOY_ENV}"
+
+ // Sets the variables used for deploying.
+ S3_BUCKET = "boilerplate-builds"
+ S3_KEY = "${env.APP_NAME}/${env.DEPLOY_ENV}/${ZIP_FILE_NAME}"
+ S3_PATH = "${S3_BUCKET}/${S3_KEY}"
+ AWS_ROLE_NAME = "qrides-bsbsi-deploy"
+ AWS_ROLE_ARN = "arn:aws:iam::xxxxxxxxxx:role/bsbsi-deploy"
+
+ // Assumes role into our AWS account (for S3 deploy).
+ sh "aws-assume-role ${AWS_ROLE_ARN} ${AWS_ROLE_NAME}"
+
+ // Deploys container to S3.
+ sh "aws --region sa-east-1 --profile ${AWS_ROLE_NAME} s3 mv ${ZIP_FILE_NAME} s3://${S3_PATH}"
+
+ // Deploys to EBS.
+ sh "aws --region sa-east-1 --profile ${AWS_ROLE_NAME} elasticbeanstalk \
+ create-application-version \
+ --application-name \"${env.APP_NAME}\" \
+ --version-label \"${PKG_NAME}\" \
+ --description \"${ZIP_FILE_NAME}\" \
+ --source-bundle S3Bucket=\"${S3_BUCKET}\",S3Key=\"${S3_KEY}\""
+
+ // Updates EBS environment.
+ sh "aws --region sa-east-1 --profile ${AWS_ROLE_NAME} elasticbeanstalk \
+ update-environment \
+ --application-name \"${env.APP_NAME}\" \
+ --environment-name \"${env.ENV_NAME}\" \
+ --version-label \"${PKG_NAME}\""
+
+ echo "Deploying complete"
+ }
+}
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2c87da1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,147 @@
+PORT ?= 5000
+DEPLOY_ENV ?= loc
+
+BIN_NAME ?= nemt-portal-api
+APP_NAME ?= nemt-portal-api
+
+BUILD_CONTAINER_NAME = ${APP_NAME}-build
+RUN_CONTAINER_NAME = ${APP_NAME}-run
+
+#############################
+## Environment definition. ##
+#############################
+
+set-loc:
+ $(eval DEPLOY_ENV := loc)
+
+set-dev:
+ $(eval DEPLOY_ENV := dev)
+
+set-stg:
+ $(eval DEPLOY_ENV := stg)
+
+set-prd:
+ $(eval DEPLOY_ENV := prd)
+
+######################
+## Building process ##
+######################
+
+# Creates the container for the building process.
+create-build-container:
+
+ # Verifies if the container already exists.
+ $(eval CONTAINER_ID:=$(shell docker ps -q --filter ancestor=$(BUILD_CONTAINER_NAME)))
+
+ # If it does, removes it.
+ if [ $(CONTAINER_ID) ]; then \
+ docker stop $(CONTAINER_ID) && \
+ docker rm $(CONTAINER_ID) && \
+ docker rmi -f $(BUILD_CONTAINER_NAME); \
+ fi
+
+ # Creates "build" container.
+ docker build -f Dockerfile.build -t ${BUILD_CONTAINER_NAME}:latest --build-arg BIN_NAME=${BIN_NAME} --build-arg APP_NAME=${APP_NAME} --force-rm .
+
+# Runs the `build` container and gets its binary.
+build: clean create-build-container
+
+ # Creates the necessary folders.
+ mkdir -p dist/static
+ mkdir -p dist/docs
+
+ # Builds inside the container.
+ docker run \
+ --name ${BUILD_CONTAINER_NAME} -d ${BUILD_CONTAINER_NAME}
+
+ # Gets the binary.
+ docker cp \
+ ${BUILD_CONTAINER_NAME}:/go/src/bitbucket.org/nemt/${APP_NAME}/${BIN_NAME} \
+ ./dist/${BIN_NAME}
+
+ # Kills the container.
+ docker stop ${BUILD_CONTAINER_NAME}
+ docker rm ${BUILD_CONTAINER_NAME}
+
+ # Copies the docs and the static files to the correct folder.
+ cp -R static/* ./dist/static/
+ cp -R docs/swagger/ ./dist/docs/
+ cp config.${DEPLOY_ENV}.toml ./dist/config.toml
+
+#################################################
+## Building, based on the current environment. ##
+#################################################
+
+build-loc: set-loc build
+
+build-dev: set-dev build
+
+build-stg: set-stg build
+
+build-prd: set-prd build
+
+#####################
+## Running process ##
+#####################
+
+create-run-container:
+
+ # Verifies if the container already exists.
+ $(eval CONTAINER_ID:=$(shell docker ps -q --filter ancestor=$(RUN_CONTAINER_NAME)))
+
+ # If it does, removes it.
+ if [ $(CONTAINER_ID) ]; then \
+ docker stop $(CONTAINER_ID) && \
+ docker rm $(CONTAINER_ID) && \
+ docker rmi -f $(RUN_CONTAINER_NAME); \
+ fi
+
+ # Creates "run" container.
+ docker build -f Dockerfile.run -t ${RUN_CONTAINER_NAME}:latest --force-rm \
+ --build-arg BIN_NAME=${BIN_NAME} \
+ --build-arg APP_NAME=${APP_NAME} \
+ .
+
+run: create-run-container
+ docker run -p ${PORT}:${PORT} -d --rm --name ${RUN_CONTAINER_NAME} ${RUN_CONTAINER_NAME}
+ echo 'Container exposing port ${PORT}.'
+
+################################################
+## Running, based on the current environment. ##
+################################################
+
+build-run-loc: build-loc create-run-container
+
+build-run-dev: build-dev create-run-container
+
+build-run-stg: build-stg create-run-container
+
+build-run-prd: build-prd create-run-container
+
+run-loc: build-run-loc run
+
+run-dev: build-run-dev run
+
+run-stg: build-run-stg run
+
+run-prd: build-run-prd run
+
+############
+## Others ##
+############
+
+clean:
+ rm -f ${BIN_NAME}
+ rm -rf dist
+
+run-host:
+ glide install
+ go build -o ${BIN_NAME} .
+ cp config.loc.toml ./config.toml
+ ./${BIN_NAME}
+
+migrate:
+ echo "Not implemented" && exit 500
+
+test:
+ echo "Not implemented" && exit 500
\ No newline at end of file
diff --git a/application/applicationservice/applicationservice.go b/application/applicationservice/applicationservice.go
new file mode 100644
index 0000000..8e32be2
--- /dev/null
+++ b/application/applicationservice/applicationservice.go
@@ -0,0 +1,43 @@
+package applicationservice
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+var (
+ instance *Service
+ once sync.Once
+)
+
+// Service holds the domain service repositories
+type Service struct {
+ Users *userService
+ Rides *rideService
+ Visits *visitService
+ Provider *providerService
+ Notification *notificationService
+ Profile *profileService
+ Organization *organizationService
+}
+
+// New returns a new domain Service instance
+func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *Service {
+ once.Do(func() {
+ instance = &Service{
+ Users: newUserService(svc, mapper),
+ Rides: newRideService(svc, mapper),
+ Visits: newVisitService(svc, mapper),
+ Provider: newProviderService(svc, mapper),
+ Notification: newNotificationService(svc, mapper, notification, cfg),
+ Profile: newProfileService(svc, mapper),
+ Organization: newOrganizationService(svc, mapper),
+ }
+ })
+
+ return instance
+}
diff --git a/application/applicationservice/notification.go b/application/applicationservice/notification.go
new file mode 100644
index 0000000..4d4ea65
--- /dev/null
+++ b/application/applicationservice/notification.go
@@ -0,0 +1,640 @@
+package applicationservice
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/pquerna/ffjson/ffjson"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/gorilla/websocket"
+ "google.golang.org/api/googleapi/transport"
+ urlshortener "google.golang.org/api/urlshortener/v1"
+ gomail "gopkg.in/gomail.v2"
+ redis "gopkg.in/redis.v5"
+)
+
+const (
+ NotificationTypeEmail = "email"
+ NOtificationTypeSMS = "sms"
+ NotificationTypeAPP = "app"
+
+ StatusPending = "pending"
+ StatusAccepted = "accepted"
+ StatusArrived = "arrived"
+ StatusPickedUp = "pickedUp"
+ StatusDroppedOff = "droppedOff"
+ StatusCanceled = "canceled"
+ StatusScheduled = "scheduled"
+ StatusWillCall = "willCall"
+
+ hourMinuteAMPM = "03:04 PM"
+)
+
+// providerService holds methods to provider application service
+type notificationService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+ notification *notificationservice.Service
+ cfg *config.Config
+ store *Store
+ pubSub *redis.PubSub
+ redisConn *redis.Client
+}
+
+// newProviderService returns a providerService instance
+func newNotificationService(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *notificationService {
+ redisClient := redis.NewFailoverClient(&redis.FailoverOptions{
+ MasterName: "master01",
+ SentinelAddrs: []string{fmt.Sprintf("%s:%v", cfg.Cache.Server, cfg.Cache.Port)},
+ Password: cfg.Cache.Pass,
+ DB: cfg.Cache.DB,
+ })
+
+ pubSub, err := redisClient.Subscribe()
+ if err != nil {
+ panic(err)
+ }
+
+ return ¬ificationService{
+ svc: svc,
+ mapEntity: mapper,
+ notification: notification,
+ cfg: cfg,
+ redisConn: redisClient,
+ store: &Store{
+ Users: make(map[string]*UserNotification),
+ redisClient: redisClient,
+ pubSub: pubSub,
+ },
+ pubSub: pubSub,
+ }
+}
+
+func (s *notificationService) secondsToMinutes(inSeconds int64) string {
+ minutes := inSeconds / 60
+ seconds := inSeconds % 60
+ str := fmt.Sprintf("%v minutes", minutes)
+
+ if seconds > 0 {
+ str += fmt.Sprintf(" %v seconds", seconds)
+ }
+
+ return str
+}
+
+func (s *notificationService) getReadyURLShortened(ride viewmodel.Ride) (string, error) {
+ const (
+ url = "https://portal.bcbsinstitute.com/#/ride/%s/%s/ready"
+ )
+
+ svc, err := urlshortener.New(&http.Client{
+ Transport: &transport.APIKey{Key: s.cfg.GoogleShortener.APIKey},
+ })
+ if err != nil {
+ return "", err
+ }
+
+ userURL := fmt.Sprintf(url, ride.UUID, ride.User.ID)
+ shortURL, err := svc.Url.Insert(&urlshortener.Url{
+ Kind: "urlshortener#url", // Not really needed
+ LongUrl: userURL,
+ }).Do()
+ if err != nil {
+ return "", err
+ }
+
+ return shortURL.Id, nil
+}
+
+func (s *notificationService) getURLShortened(ride viewmodel.Ride) (string, error) {
+ const (
+ url = "https://portal.bcbsinstitute.com/#/ride/%s/%s"
+ )
+
+ svc, err := urlshortener.New(&http.Client{
+ Transport: &transport.APIKey{Key: s.cfg.GoogleShortener.APIKey},
+ })
+ if err != nil {
+ return "", err
+ }
+
+ userURL := fmt.Sprintf(url, ride.UUID, ride.User.ID)
+ shortURL, err := svc.Url.Insert(&urlshortener.Url{
+ Kind: "urlshortener#url", // Not really needed
+ LongUrl: userURL,
+ }).Do()
+ if err != nil {
+ return "", err
+ }
+
+ return shortURL.Id, nil
+}
+
+func (s *notificationService) SendNotification(state string, ride viewmodel.Ride, lyftRide viewmodel.RideRequest) error {
+ notifications := make([]viewmodel.Notification, 0)
+ url, err := s.getURLShortened(ride)
+ if err != nil {
+ fmt.Println("Error to short url: ", err)
+ }
+
+ loc, _ := time.LoadLocation("America/Chicago")
+ switch state {
+ case StatusWillCall:
+ visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
+ visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
+
+ messageMemberSMS := fmt.Sprintf(MessageSMSWillCallMember, visitTime, ride.Route.Destination.Name, visitDate)
+ messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageMemberEmail := fmt.Sprintf(MessageEmailWillCallMember, visitTime, ride.Route.Destination.Name, visitDate)
+ //messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+
+ urlReady, err := s.getReadyURLShortened(ride)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ messageMemberSMS += "\n" + fmt.Sprintf(MessageSMSIAmReadyOrClick, ride.Route.Destination.Name, urlReady)
+ messageMemberEmail += "\n" + fmt.Sprintf(MessageEmailIAmReadyOrClick, ride.Route.Destination.Name, urlReady)
+
+ messageDispatcherSMS := fmt.Sprintf(MessageSMSWillCallDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate)
+ messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageDispatcherEmail := fmt.Sprintf(MessageEmailWillCallDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate)
+ //messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+
+ notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSWillCallMemberTitle, messageMemberSMS, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSWillCallDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailWillCallMemberTitle, messageMemberEmail, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailWillCallDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "app", "Ride Scheduled "+strings.ToLower(ride.TripType.Value), fmt.Sprintf(MessageAppWillCallMemberTitle, ride.Status.Value, ride.Route.Destination.Address), false, "ride"))
+ notifications = append(notifications, s.GetNotification(ride, "app", "Ride Scheduled "+strings.ToLower(ride.TripType.Value), fmt.Sprintf(MessageAppWillCallDispatcherTitle, ride.Status.Value, ride.Route.Destination.Address), true, "ride"))
+ case StatusScheduled:
+ dateFormat := ride.PickupTime.In(loc).Format("01/02/2006 03:04 PM")
+ visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
+ pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
+ visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
+
+ if ride.TripType.Key == "from_visit" && lyftRide.ReturnTime != nil {
+ dateFormat = lyftRide.ReturnTime.In(loc).Format("01/02/2006 03:04 PM")
+ pickupTime = lyftRide.ReturnTime.In(loc).Format(hourMinuteAMPM)
+ }
+
+ messageMemberSMS := fmt.Sprintf(MessageSMSScheduledMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageMemberEmail := fmt.Sprintf(MessageEmailScheduledMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ //messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+
+ messageDispatcherSMS := fmt.Sprintf(MessageSMSScheduledDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageDispatcherEmail := fmt.Sprintf(MessageEmailScheduledDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ //messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSScheduledMemberTitle, dateFormat), messageMemberSMS, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSScheduledDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherSMS, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailScheduledMemberTitle, dateFormat), messageMemberEmail, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailScheduledDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherEmail, true, ""))
+
+ // if ride.TripType.Key == "to_visit" {
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+strings.ToLower(ride.TripType.Value), ride.Status.Value), fmt.Sprintf(MessageAppScheduledMemberTitle, pickupTime, ride.Route.Origin.Name), false, "ride"))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+strings.ToLower(ride.TripType.Value), ride.Status.Value), fmt.Sprintf(MessageAppScheduledDispatcherTitle, pickupTime, ride.Route.Origin.Name), true, "ride"))
+ // } else if ride.TripType.Key == "from_visit" {
+ // notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("Ride %s "+strings.ToLower(ride.TripType.Value), StatusScheduled), fmt.Sprintf(MessageAppScheduledMemberTitle, pickupTime, ride.Route.Destination.Name), false, "ride"))
+ // notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("Ride %s "+strings.ToLower(ride.TripType.Value), StatusScheduled), fmt.Sprintf(MessageAppScheduledDispatcherTitle, pickupTime, ride.Route.Destination.Name), true, "ride"))
+ // }
+ case StatusPending:
+ dateFormat := ride.PickupTime.In(loc).Format("01/02/2006 03:04 PM")
+ visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
+ pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
+ visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
+
+ messageMemberSMS := fmt.Sprintf(MessageSMSPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageMemberEmail := fmt.Sprintf(MessageEmailPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ //messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+
+ messageDispatcherSMS := fmt.Sprintf(MessageSMSPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageDispatcherEmail := fmt.Sprintf(MessageEmailPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+ //messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
+
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPendingMemberTitle, dateFormat), messageMemberSMS, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPendingDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherSMS, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPendingMemberTitle, dateFormat), messageMemberEmail, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPendingDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherEmail, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPendingMemberTitle, pickupTime, ride.Route.Origin.Name), false, "ride"))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPendingDispatcherTitle, pickupTime, ride.Route.Origin.Name), true, "ride"))
+ case StatusAccepted:
+ pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
+
+ messageMemberSMS := fmt.Sprintf(MessageSMSAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageMemberEmail := fmt.Sprintf(MessageEmailAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ //messageMemberApp := fmt.Sprintf(MessageAppAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, visitTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+
+ messageDispatcherSMS := fmt.Sprintf(MessageSMSAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageDispatcherEmail := fmt.Sprintf(MessageEmailAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ //messageDispatcherApp := fmt.Sprintf(MessageAppAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, visitTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+
+ notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSAcceptedMemberTitle, messageMemberSMS, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSAcceptedDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailAcceptedMemberTitle, messageMemberEmail, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailAcceptedDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppAcceptedMemberTitle, s.secondsToMinutes(*lyftRide.Origin.ETASeconds), ride.Route.Origin.Name), false, "ride"))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppAcceptedDispatcherTitle, s.secondsToMinutes(*lyftRide.Origin.ETASeconds), ride.Route.Origin.Name), true, "ride"))
+ case StatusArrived:
+ messageMemberSMS := fmt.Sprintf(MessageSMSArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageMemberEmail := fmt.Sprintf(MessageEmailArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ //messageMemberApp := fmt.Sprintf(MessageAppArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+
+ messageDispatcherSMS := fmt.Sprintf(MessageSMSArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageDispatcherEmail := fmt.Sprintf(MessageEmailArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+ //messageDispatcherApp := fmt.Sprintf(MessageAppArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
+
+ notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSArrivedMemberTitle, messageMemberSMS, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSArrivedDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailArrivedMemberTitle, messageMemberEmail, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailArrivedDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "app", "Your ride is HERE", fmt.Sprintf(MessageAppArrivedMemberTitle, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate), false, "ride"))
+ notifications = append(notifications, s.GetNotification(ride, "app", "Waiting for member", fmt.Sprintf(MessageAppArrivedDispatcherTitle, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate), true, "ride"))
+ case StatusPickedUp:
+ dateFormat := time.Now().In(loc).Format("01/02/2006 03:04 PM")
+ visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
+ pickupTime := lyftRide.Pickup.Time.In(loc).Format(hourMinuteAMPM)
+
+ messageDispatcherSMS := fmt.Sprintf(MessageSMSPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
+ messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
+ messageDispatcherEmail := fmt.Sprintf(MessageEmailPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
+ //messageDispatcherApp := fmt.Sprintf(MessageAppPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
+
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPickedUpDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPickedUpDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPickedUpDispatcherTitle, pickupTime), true, "ride"))
+ case StatusDroppedOff:
+ dateFormat := time.Now().In(loc).Format("01/02/2006 03:04 PM")
+ dropOffTime := lyftRide.DropOff.Time.In(loc).Format(hourMinuteAMPM)
+
+ // messageMemberSMS := MessageSMSDroppedOffMember
+ // messageMemberEmail := MessageEmailDroppedOffMember
+
+ // if ride.Visit.TripType.Key == "roundtrip_call" && ride.TripType.Key == "to_visit" {
+ // entityRide, err := s.svc.Rides.GetByUUID(ride.UUID)
+ // if err != nil {
+ // fmt.Println(err)
+ // }
+
+ // var nextRide entity.Ride
+ // for _, r := range entityRide.Visit.Rides {
+ // fmt.Println("Ride Tryp Type: ", r.TripType.Key)
+ // if r.TripType.Key == "from_visit_call" {
+ // nextRide = r
+ // }
+ // }
+
+ // fmt.Println("NextRide Found: ", nextRide.UUID)
+ // if nextRide.UUID != "" {
+ // urlReady, err := s.getReadyURLShortened(nextRide)
+ // if err != nil {
+ // fmt.Println(err)
+ // }
+
+ // messageMemberSMS += "\n" + fmt.Sprintf(MessageSMSIAmReadyOrClick, nextRide.Route.Destination.Name, urlReady)
+ // messageMemberEmail += "\n" + fmt.Sprintf(MessageEmailIAmReadyOrClick, nextRide.Route.Destination.Name, urlReady)
+ // }
+ // }
+
+ // fmt.Println("SMS Message: ", messageMemberSMS)
+
+ messageDispatcherSMS := fmt.Sprintf(MessageSMSDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
+ messageDispatcherEmail := fmt.Sprintf(MessageEmailDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
+ //messageDispatcherApp := fmt.Sprintf(MessageAppDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
+
+ //notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSDroppedOffMemberTitle, messageMemberSMS, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSDroppedOffDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
+ //notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailDroppedOffMemberTitle, messageMemberEmail, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailDroppedOffDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
+ //notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf(MessageAppDroppedOffMemberTitle, ride.Route.Destination.Name), fmt.Sprintf(MessageAppDroppedOffMemberTitle, ride.Route.Destination.Name), false, "ride"))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppDroppedOffDispatcherTitle, dropOffTime), true, "ride"))
+ case StatusCanceled:
+ visitTime := ride.VisitDate.Format(hourMinuteAMPM)
+ visitDate := ride.VisitDate.Format("01/02/2006")
+
+ var messageMemberSMS string
+ var messageMemberSMSTitle string
+ var messageMemberEmail string
+ var messageMemberEmailTitle string
+ //var messageMemberApp string
+ var messageMemberAppTitle string
+
+ var messageDispatcherSMS string
+ var messageDispatcherSMSTitle string
+ var messageDispatcherEmail string
+ var messageDispatcherEmailTitle string
+ //var messageDispatcherApp string
+ var messageDispatcherAppTitle string
+
+ if lyftRide.CanceledBy == "driver" {
+ messageMemberSMS = fmt.Sprintf(MessageSMSCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
+ messageMemberSMSTitle = MessageSMSCanceledByDriverMemberTitle
+ messageMemberEmail = fmt.Sprintf(MessageEmailCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
+ messageMemberEmailTitle = MessageEmailCanceledByDriverMemberTitle
+ //messageMemberApp = fmt.Sprintf(MessageAppCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
+ messageMemberAppTitle = MessageAppCanceledByDriverMemberTitle
+
+ messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
+ messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledByDriverDispatcherTitle, ride.User.Name)
+ messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
+ messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledByDriverDispatcherTitle, ride.User.Name)
+ //messageDispatcherApp = fmt.Sprintf(MessageAppCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
+ messageDispatcherAppTitle = MessageAppCanceledByDriverDispatcherTitle
+ } else if lyftRide.CanceledBy == "no_drivers_available" {
+ messageMemberSMS = fmt.Sprintf(MessageSMSCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
+ messageMemberSMSTitle = MessageSMSCanceledNoDriverMemberTitle
+ messageMemberEmail = fmt.Sprintf(MessageEmailCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
+ messageMemberEmailTitle = MessageEmailCanceledNoDriverMemberTitle
+ //messageMemberApp = fmt.Sprintf(MessageAppCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
+ messageMemberAppTitle = MessageAppCanceledNoDriverMemberTitle
+
+ messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
+ messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledNoDriverDispatcherTitle, ride.User.Name)
+ messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
+ messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledNoDriverDispatcherTitle, ride.User.Name)
+ //messageDispatcherApp = fmt.Sprintf(MessageAppCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
+ messageDispatcherAppTitle = MessageAppCanceledNoDriverDispatcherTitle
+ } else {
+ messageMemberSMS = fmt.Sprintf(MessageSMSCanceledMember, visitTime, ride.Visit.ExternalID)
+ messageMemberSMSTitle = MessageSMSCanceledMemberTitle
+ messageMemberEmail = fmt.Sprintf(MessageEmailCanceledMember, visitTime, ride.Visit.ExternalID)
+ messageMemberEmailTitle = MessageEmailCanceledMemberTitle
+ //messageMemberApp = fmt.Sprintf(MessageAppCanceledMember, visitTime, ride.Visit.ExternalID)
+ messageMemberAppTitle = MessageAppCanceledMemberTitle
+
+ messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledDispatcher, visitTime, ride.Visit.ExternalID)
+ messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledDispatcherTitle, ride.User.Name)
+ messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledDispatcher, visitTime, ride.Visit.ExternalID)
+ messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledDispatcherTitle, ride.User.Name)
+ //messageDispatcherApp = fmt.Sprintf(MessageAppCanceledDispatcher, visitTime, ride.Visit.ExternalID)
+ messageDispatcherAppTitle = MessageAppCanceledDispatcherTitle //fmt.Sprintf(MessageAppCanceledDispatcherTitle, ride.User.Name)
+ }
+
+ notifications = append(notifications, s.GetNotification(ride, "sms", messageMemberSMSTitle, messageMemberSMS, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "sms", messageDispatcherSMSTitle, messageDispatcherSMS, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", messageMemberEmailTitle, messageMemberEmail, false, ""))
+ notifications = append(notifications, s.GetNotification(ride, "email", messageDispatcherEmailTitle, messageDispatcherEmail, true, ""))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), messageMemberAppTitle, false, "ride"))
+ notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), messageDispatcherAppTitle, true, "ride"))
+ }
+
+ notifications, err = s.SendNotifications(notifications)
+ if err != nil {
+ fmt.Println("Error to notify")
+ return err
+ }
+
+ return nil
+}
+
+func (s *notificationService) GetNotification(ride viewmodel.Ride, notificationType string, subject string, message string, isDispatcher bool, messageType string) viewmodel.Notification {
+ retVal := viewmodel.Notification{
+ Type: notificationType,
+ Message: message,
+ Subject: subject,
+ Ride: ride,
+ User: ride.User,
+ CreatedUser: ride.CreatedUser,
+ Read: false,
+ MessageType: messageType,
+ }
+
+ if isDispatcher {
+ retVal.User = ride.CreatedUser
+ retVal.CreatedUser = ride.User
+ }
+
+ switch notificationType {
+ case NotificationTypeEmail:
+ if isDispatcher {
+ retVal.To = *ride.CreatedUser.Email
+ } else {
+ retVal.To = *ride.User.Email
+ }
+ case NOtificationTypeSMS:
+ if isDispatcher {
+ retVal.To = *ride.CreatedUser.PhoneNumber
+ } else {
+ retVal.To = *ride.User.PhoneNumber
+ }
+ case NotificationTypeAPP:
+ if isDispatcher {
+ retVal.To = ride.CreatedUser.ID
+ } else {
+ retVal.To = ride.User.ID
+ }
+ }
+
+ return retVal
+}
+
+func (s *notificationService) SendMessage(message viewmodel.Message) error {
+ bMessage, err := ffjson.Marshal(message)
+ if err != nil {
+ return err
+ }
+
+ return s.store.redisClient.Publish(message.DeliveryID, string(bMessage)).Err()
+}
+
+func (s *notificationService) GetByUserUUIDAndReadStatus(user viewmodel.User, contactType string, isRead bool) ([]viewmodel.Notification, error) {
+ n, err := s.svc.Notification.GetByUserUUIDAndReadStatus(user.ID, contactType, isRead)
+ if err != nil {
+ return nil, err
+ }
+
+ authUser, err := s.svc.Users.GetByUUID(user.ID, "")
+ if err != nil {
+ return nil, err
+ }
+
+ if !isRead {
+ for i, _ := range n {
+ r, err := s.svc.Rides.GetByID(n[i].Ride.ID, authUser)
+ if err != nil {
+ return nil, err
+ }
+
+ n[i].Ride = r
+ }
+ }
+
+ return s.mapEntity.Notification.ToNotificationModelSlice(n), nil
+}
+
+func (s *notificationService) Subscribe(user viewmodel.User, conn *websocket.Conn) (*UserNotification, error) {
+ return s.store.Subscribe(user, conn)
+}
+
+func (s *notificationService) DeliverMessage() {
+ for {
+ v, _ := s.pubSub.Receive()
+ switch t := v.(type) {
+ case *redis.Message:
+ var m viewmodel.Message
+ ffjson.Unmarshal([]byte(t.Payload), &m)
+ s.store.FindAndDeliver(m)
+ case error:
+ fmt.Println("Error to delivery messages: ", t.Error())
+ return
+ default:
+ if t != nil {
+ fmt.Println("Unknown Event: ", t)
+ fmt.Println("Type: ", reflect.TypeOf(t))
+ }
+ }
+ }
+}
+
+//FindAndDeliver will send a message to an open channel
+func (s *Store) FindAndDeliver(m viewmodel.Message) {
+ if s.Users[m.DeliveryID] != nil {
+ if s.Users[m.DeliveryID].ID != "" {
+ if len(s.Users[m.DeliveryID].Conn) > 0 {
+ for i, _ := range s.Users[m.DeliveryID].Conn {
+ if s.Users[m.DeliveryID].Conn[i] != nil {
+ if err := s.Users[m.DeliveryID].Conn[i].WriteJSON(m); err != nil {
+ s.Users[m.DeliveryID].Conn[i] = nil
+ }
+ }
+ }
+ }
+ return
+ }
+ }
+}
+
+//Subscribe add the user to a subscription
+func (s *Store) Subscribe(user viewmodel.User, conn *websocket.Conn) (*UserNotification, error) {
+ u := s.Users[user.ID]
+ if u == nil {
+ u := &UserNotification{
+ ID: user.ID,
+ Conn: []*websocket.Conn{conn},
+ User: user,
+ }
+ s.Users[u.ID] = u
+ } else {
+ u.Conn = append(u.Conn, conn)
+ s.Users[u.ID] = u
+ }
+
+ err := s.pubSub.Subscribe(user.ID)
+ if err != nil {
+ return nil, err
+ }
+ s.Lock()
+ defer s.Unlock()
+
+ return u, nil
+}
+
+func (s *notificationService) ReadStatus(notificationUUID string, isRead bool) error {
+ return s.svc.Notification.ReadStatus(notificationUUID, isRead)
+}
+
+// SendNotifications will send all the notifications to email or SMS
+func (s *notificationService) SendNotifications(notifications []viewmodel.Notification) ([]viewmodel.Notification, error) {
+ if len(notifications) > 0 {
+ retVal := make([]viewmodel.Notification, 0)
+ for _, n := range notifications {
+ if n.To != "" {
+ notification := s.mapEntity.Notification.ToNotificationEntity(n)
+ notification, err := s.svc.Notification.Create(notification)
+ if err != nil {
+ return nil, err
+ }
+
+ switch n.Type {
+ case NOtificationTypeSMS:
+ if n.From == "" {
+ if err := s.notification.Twilio.SendSMS(s.cfg.Twilio.Sender, n.To, n.Message); err != nil {
+ fmt.Println("Error to send SMS: ", err.Error())
+ }
+ if err := s.notification.Twilio.SendSMS(s.cfg.Twilio.Sender, "+17083038497", n.Message); err != nil {
+ fmt.Println("Error to send SMS: ", err.Error())
+ }
+ } else {
+ if err := s.notification.Twilio.SendSMS(n.From, n.To, n.Message); err != nil {
+ fmt.Println("Error to send SMS: ", err.Error())
+ }
+ if err := s.notification.Twilio.SendSMS(n.From, "+17083038497", n.Message); err != nil {
+ fmt.Println("Error to send SMS: ", err.Error())
+ }
+ }
+ case NotificationTypeEmail:
+ m := gomail.NewMessage()
+ m.SetHeader("From", s.cfg.Email.Sender)
+ m.SetHeader("To", n.To)
+ m.SetHeader("Subject", n.Subject)
+ m.SetBody("text/plain", n.Message)
+ d := gomail.NewDialer(s.cfg.Email.Server, s.cfg.Email.Port, s.cfg.Email.User, s.cfg.Email.Pass)
+
+ if err := d.DialAndSend(m); err != nil {
+ fmt.Println("Error to send Email: ", err.Error())
+ }
+
+ m = gomail.NewMessage()
+ m.SetHeader("From", s.cfg.Email.Sender)
+ m.SetHeader("To", "nemt@brighterdevelopment.com")
+ m.SetHeader("Subject", n.Subject)
+ m.SetBody("text/plain", n.Message)
+
+ if err := d.DialAndSend(m); err != nil {
+ fmt.Println("Error to send Email: ", err.Error())
+ }
+ case NotificationTypeAPP:
+ m := viewmodel.Message{
+ DeliveryID: n.To,
+ NotificationID: notification.UUID,
+ CreateDate: notification.Created,
+ Read: notification.Read,
+ Content: viewmodel.MessageContent{
+ Type: n.MessageType,
+ Subject: n.Subject,
+ Content: n.Message,
+ Payload: n.Ride,
+ },
+ }
+
+ if err := s.SendMessage(m); err != nil {
+ fmt.Println("Error to send notification to the users: ", err.Error())
+ }
+ }
+ retVal = append(retVal, s.mapEntity.Notification.ToNotificationModel(notification))
+ }
+ }
+ return retVal, nil
+ }
+ return notifications, nil
+}
+
+type UserNotification struct {
+ ID string
+ Conn []*websocket.Conn
+ User viewmodel.User
+}
+
+type Store struct {
+ Users map[string]*UserNotification
+ redisClient *redis.Client
+ pubSub *redis.PubSub
+ sync.Mutex
+}
diff --git a/application/applicationservice/notificationmessage.go b/application/applicationservice/notificationmessage.go
new file mode 100644
index 0000000..3d33fe7
--- /dev/null
+++ b/application/applicationservice/notificationmessage.go
@@ -0,0 +1,131 @@
+package applicationservice
+
+const (
+ MessageSMSIAmReadyOrClick = "When you ready to go back to %s, click on the following link:\n %s\n or reply this message with I AM READY"
+ MessageEmailIAmReadyOrClick = "When you are ready to go back to %s, click on the following link:\n %s"
+
+ MessageSMSReplyOrCancel = "Reply CANCEL RIDE to cancel or DRIVER to contact driver"
+ MessageSMSPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageSMSPendingMemberTitle = "Ride Pending for %s"
+ MessageSMSPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageSMSPendingDispatcherTitle = "Ride Pending for %s on %s"
+ MessageEmailPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageEmailPendingMemberTitle = "Ride Pending for %s"
+ MessageEmailPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageEmailPendingDispatcherTitle = "Ride Pending for %s on %s"
+ MessageAppPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageAppPendingMemberTitle = "Pickup: %s | %s"
+ MessageAppPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageAppPendingDispatcherTitle = "Pickup: %s | %s"
+
+ MessageSMSWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
+ MessageSMSWillCallMemberTitle = "Ride Pending for %s"
+ MessageSMSWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
+ MessageSMSWillCallDispatcherTitle = "Ride Pending for %s"
+ MessageEmailWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
+ MessageEmailWillCallMemberTitle = "Ride Pending for %s"
+ MessageEmailWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
+ MessageEmailWillCallDispatcherTitle = "Ride Pending for %s"
+ MessageAppWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
+ MessageAppWillCallMemberTitle = "Pickup: %s | %s"
+ MessageAppWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
+ MessageAppWillCallDispatcherTitle = "Pickup: %s | %s"
+
+ MessageSMSScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageSMSScheduledMemberTitle = "Ride Scheduled for %s"
+ MessageSMSScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageSMSScheduledDispatcherTitle = "Ride Scheduled for %s on %s"
+ MessageEmailScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageEmailScheduledMemberTitle = "Ride Scheduled for %s"
+ MessageEmailScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageEmailScheduledDispatcherTitle = "Ride Scheduled for %s on %s"
+ MessageAppScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageAppScheduledMemberTitle = "Pickup: %s | %s"
+ MessageAppScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
+ MessageAppScheduledDispatcherTitle = "Pickup: %s | %s"
+
+ MessageSMSAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageSMSAcceptedMemberTitle = "Your Ride is on the way !"
+ MessageSMSAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageSMSAcceptedDispatcherTitle = "Ride Accepted for %s"
+ MessageEmailAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageEmailAcceptedMemberTitle = "Your Ride is on the way !"
+ MessageEmailAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageEmailAcceptedDispatcherTitle = "Ride Accepted for %s"
+ MessageAppAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageAppAcceptedMemberTitle = "ETA: %s at %s"
+ MessageAppAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageAppAcceptedDispatcherTitle = "ETA: %s at %s"
+
+ MessageSMSArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageSMSArrivedMemberTitle = "Your Ride is HERE !"
+ MessageSMSArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageSMSArrivedDispatcherTitle = "Ride Arrived for %s"
+ MessageEmailArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageEmailArrivedMemberTitle = "Your Ride is HERE !"
+ MessageEmailArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageEmailArrivedDispatcherTitle = "Ride Arrived for %s"
+ MessageAppArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageAppArrivedMemberTitle = "Look for %s %s %s (%s)"
+ MessageAppArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
+ MessageAppArrivedDispatcherTitle = "Look for %s %s %s (%s)"
+
+ MessageSMSPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
+ MessageSMSPickedUpDispatcherTitle = "%s is in Transit"
+ MessageEmailPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
+ MessageEmailPickedUpDispatcherTitle = "%s is in Transit"
+ MessageAppPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
+ MessageAppPickedUpDispatcherTitle = "Actual Pickup Time: %s"
+
+ MessageSMSDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
+ MessageSMSDroppedOffDispatcherTitle = "%s has arrived"
+ MessageEmailDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
+ MessageEmailDroppedOffDispatcherTitle = "%s has arrived"
+ MessageAppDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
+ MessageAppDroppedOffDispatcherTitle = "Arrival Time: %s"
+ MessageSMSDroppedOffMember = "Your ride has been ended, Thank you."
+ MessageSMSDroppedOffMemberTitle = "Ride Ended"
+ MessageEmailDroppedOffMember = "Your ride has been ended, Thank you."
+ MessageEmailDroppedOffMemberTitle = "Ride Ended"
+ MessageAppDroppedOffMember = "Your ride has been ended, Thank you."
+ MessageAppDroppedOffMemberTitle = "Arrived to %s"
+
+ MessageSMSCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
+ MessageSMSCanceledByDriverMemberTitle = "Your Ride has been Canceled"
+ MessageSMSCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
+ MessageSMSCanceledByDriverDispatcherTitle = "Ride for %s Canceled"
+ MessageEmailCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
+ MessageEmailCanceledByDriverMemberTitle = "Your Ride has been Canceled"
+ MessageEmailCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
+ MessageEmailCanceledByDriverDispatcherTitle = "Ride for %s Canceled"
+ MessageAppCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
+ MessageAppCanceledByDriverMemberTitle = "Canceled by Driver"
+ MessageAppCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
+ MessageAppCanceledByDriverDispatcherTitle = "Canceled by Driver"
+
+ MessageSMSCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
+ MessageSMSCanceledNoDriverMemberTitle = "Your Ride has been Canceled"
+ MessageSMSCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
+ MessageSMSCanceledNoDriverDispatcherTitle = "Ride for %s Canceled"
+ MessageEmailCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
+ MessageEmailCanceledNoDriverMemberTitle = "Your Ride has been Canceled"
+ MessageEmailCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
+ MessageEmailCanceledNoDriverDispatcherTitle = "Ride for %s Canceled"
+ MessageAppCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
+ MessageAppCanceledNoDriverMemberTitle = "No drivers available"
+ MessageAppCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
+ MessageAppCanceledNoDriverDispatcherTitle = "No drivers available"
+
+ MessageSMSCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
+ MessageSMSCanceledMemberTitle = "Your Ride has been Canceled"
+ MessageSMSCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
+ MessageSMSCanceledDispatcherTitle = "Ride for %s Canceled"
+ MessageEmailCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
+ MessageEmailCanceledMemberTitle = "Your Ride has been Canceled"
+ MessageEmailCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
+ MessageEmailCanceledDispatcherTitle = "Ride for %s Canceled"
+ MessageAppCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
+ MessageAppCanceledMemberTitle = "Canceled by Member"
+ MessageAppCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
+ MessageAppCanceledDispatcherTitle = "Canceled by Member"
+)
diff --git a/application/applicationservice/organization.go b/application/applicationservice/organization.go
new file mode 100644
index 0000000..9d4d635
--- /dev/null
+++ b/application/applicationservice/organization.go
@@ -0,0 +1,230 @@
+package applicationservice
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "github.com/pquerna/ffjson/ffjson"
+)
+
+// providerService holds methods to provider application service
+type organizationService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+}
+
+// newProviderService returns a providerService instance
+func newOrganizationService(svc *service.Service, mapper *entitymapping.Mapper) *organizationService {
+ return &organizationService{
+ svc: svc,
+ mapEntity: mapper,
+ }
+}
+
+func (s *organizationService) GetAllTypes() ([]viewmodel.OrganizationType, error) {
+ result, err := s.svc.Organization.GetAllTypes()
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Organization.ToOrganizationTypeModelSlice(result), nil
+}
+
+func (s *organizationService) GetByType(organizationTypeKey string) ([]viewmodel.Organization, error) {
+ result, err := s.svc.Organization.GetByType(organizationTypeKey)
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
+}
+
+func (s *organizationService) GetByUUID(organizationUUID string) (viewmodel.Organization, error) {
+ result, err := s.svc.Organization.GetByUUID(organizationUUID)
+ if err != nil {
+ return viewmodel.Organization{}, err
+ }
+ return s.mapEntity.Organization.ToOrganizationModel(result), nil
+}
+
+func (s *organizationService) GetByName(name string, searchType string) ([]viewmodel.Organization, error) {
+ result, err := s.svc.Organization.GetByName(name, searchType)
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
+}
+
+func (s *organizationService) SetParentOrganization(organizationUUID string, parentOrganizationUUID string) (viewmodel.Organization, error) {
+ child, err := s.svc.Organization.GetByUUID(organizationUUID)
+ if err != nil {
+ return viewmodel.Organization{}, err
+ }
+
+ parent, err := s.svc.Organization.GetByUUID(parentOrganizationUUID)
+ if err != nil {
+ return viewmodel.Organization{}, err
+ }
+
+ if err := s.svc.Organization.SetParentOrganization(child.ID, parent.ID); err != nil {
+ return viewmodel.Organization{}, err
+ }
+
+ return s.GetByUUID(organizationUUID)
+}
+
+func (s *organizationService) InactivateOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) error {
+ entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
+ entityAddress.Organization = &entity.Organization{
+ UUID: organizationUUID,
+ }
+
+ user, err := s.svc.Users.GetByUUID(address.UpdatedUser.ID, "")
+ if err != nil {
+ return err
+ }
+ entityAddress.UpdatedUser = user
+
+ if err := s.svc.Organization.InactivateOrganizationAddress(entityAddress); err != nil {
+ return err
+ } else {
+ return nil
+ }
+}
+
+func (s *organizationService) SetOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) (viewmodel.OrganizationAddress, error) {
+ entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
+ entityAddress.Organization = &entity.Organization{
+ UUID: organizationUUID,
+ }
+
+ user, err := s.svc.Users.GetByUUID(address.CreatedUser.ID, "")
+ if err != nil {
+ return viewmodel.OrganizationAddress{}, err
+ }
+
+ entityAddress.CreatedUser = user
+ entityAddress.UpdatedUser = user
+
+ entityAddress, err = s.svc.Organization.SetOrganizationAddress(entityAddress)
+ if err != nil {
+ return viewmodel.OrganizationAddress{}, err
+ }
+
+ return s.mapEntity.Organization.ToOrganizationAddressModel(entityAddress), nil
+}
+
+func (s *organizationService) InactivateOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) error {
+ entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
+ entityContact.Organization = &entity.Organization{
+ UUID: organizationUUID,
+ }
+
+ user, err := s.svc.Users.GetByUUID(contact.CreatedUser.ID, "")
+ if err != nil {
+ return err
+ }
+ entityContact.UpdatedUser = user
+
+ if err := s.svc.Organization.InactivateOrganizationContact(entityContact); err != nil {
+ return err
+ } else {
+ return nil
+ }
+}
+
+func (s *organizationService) SetOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) (viewmodel.OrganizationContact, error) {
+ entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
+ entityContact.Organization = &entity.Organization{
+ UUID: organizationUUID,
+ }
+
+ user, err := s.svc.Users.GetByUUID(contact.CreatedUser.ID, "")
+ if err != nil {
+ return viewmodel.OrganizationContact{}, err
+ }
+
+ entityContact.CreatedUser = user
+ entityContact.UpdatedUser = user
+
+ entityContact, err = s.svc.Organization.SetOrganizationContact(entityContact)
+ if err != nil {
+ return viewmodel.OrganizationContact{}, err
+ }
+
+ return s.mapEntity.Organization.ToOrganizationContactModel(entityContact), nil
+}
+
+func (s *organizationService) AddOrganization(organization viewmodel.Organization, user viewmodel.User) (viewmodel.Organization, error) {
+ enOrg := s.mapEntity.Organization.ToOrganizationEntity(organization)
+ enUser := s.mapEntity.User.ToUserEntity(user)
+
+ author, err := s.svc.Users.GetByUUID(organization.Author.ID, "")
+ if err != nil {
+ return viewmodel.Organization{}, nil
+ }
+ enOrg.Author = author
+ enOrg.LastEditor = enOrg.Author
+
+ if organization.Reference != nil {
+ switch organization.Type.Key {
+ case "provider":
+ var provider npdmodel.ProviderResponse
+ bProvider, err := ffjson.Marshal(organization.Reference)
+ if err != nil {
+ fmt.Println("Error to marshal provider")
+ return viewmodel.Organization{}, nil
+ }
+ if err := ffjson.Unmarshal(bProvider, &provider); err != nil {
+ fmt.Println("Error to convert provider")
+ return viewmodel.Organization{}, nil
+ }
+
+ eProviders, err := s.svc.Provider.Save(s.mapEntity.Provider.ToProviderEntitySlice([]npdmodel.ProviderResponse{provider}), enUser)
+ if err != nil {
+ fmt.Println("Error to save provider")
+ return viewmodel.Organization{}, nil
+ }
+ respProvider := eProviders[0]
+ enOrg.ReferenceID = respProvider.ProviderID
+
+ lat, _ := strconv.ParseFloat(provider.Latitude, 64)
+ long, _ := strconv.ParseFloat(provider.Longitude, 64)
+ address := entity.OrganizationAddress{
+ InternalID: provider.MukID,
+ Name: "Main Address",
+ Address: fmt.Sprintf("%s %s - %s, %s (%s)", provider.StreetName1, provider.StreetName2, provider.CityName, provider.State, provider.ZipCode),
+ Latitude: lat,
+ Longitude: long,
+ CreatedUser: enOrg.Author,
+ UpdatedUser: enOrg.LastEditor,
+ }
+ enOrg.Addresses = append(enOrg.Addresses, address)
+ fmt.Println("Phone Number: ", provider.PhoneNumber)
+ if provider.PhoneNumber != "" {
+ formattedPhone := "+1" + strings.Replace(provider.PhoneNumber, "-", "", -1)
+ contact := entity.OrganizationContact{
+ Type: entity.ContactType{
+ Key: "phone",
+ },
+ Contact: formattedPhone,
+ Name: "Main Phone",
+ CreatedUser: enOrg.Author,
+ UpdatedUser: enOrg.LastEditor,
+ }
+ enOrg.Contacts = append(enOrg.Contacts, contact)
+ }
+ }
+ }
+
+ enOrg, err = s.svc.Organization.AddOrganization(enOrg)
+ if err != nil {
+ return viewmodel.Organization{}, nil
+ }
+
+ return s.GetByUUID(enOrg.UUID)
+}
diff --git a/application/applicationservice/profile.go b/application/applicationservice/profile.go
new file mode 100644
index 0000000..b5a9ae3
--- /dev/null
+++ b/application/applicationservice/profile.go
@@ -0,0 +1,58 @@
+package applicationservice
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+)
+
+// providerService holds methods to provider application service
+type profileService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+}
+
+// newProviderService returns a providerService instance
+func newProfileService(svc *service.Service, mapper *entitymapping.Mapper) *profileService {
+ return &profileService{
+ svc: svc,
+ mapEntity: mapper,
+ }
+}
+
+func (s *profileService) GetAll() ([]viewmodel.Profile, error) {
+ result, err := s.svc.Profile.GetAll()
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Profile.ToProfileModelSlice(result), nil
+}
+
+func (s *profileService) GetByKey(key string) (viewmodel.Profile, error) {
+ result, err := s.svc.Profile.GetByKey(key)
+ if err != nil {
+ return viewmodel.Profile{}, err
+ }
+ return s.mapEntity.Profile.ToProfileModel(result), nil
+}
+
+func (s *profileService) GetVisibles(visible bool) ([]viewmodel.Profile, error) {
+ result, err := s.svc.Profile.GetVisibles(visible)
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Profile.ToProfileModelSlice(result), nil
+}
+
+func (s *profileService) GetByOrganizationType(organizationTypeKey string) ([]viewmodel.Profile, error) {
+ orgType, err := s.svc.Organization.GetTypeByKey(organizationTypeKey)
+ if err != nil {
+ return nil, err
+ }
+
+ result, err := s.svc.Profile.GetByOrganizationType(orgType.ID)
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Profile.ToProfileModelSlice(result), nil
+}
diff --git a/application/applicationservice/provider.go b/application/applicationservice/provider.go
new file mode 100644
index 0000000..ce4ff31
--- /dev/null
+++ b/application/applicationservice/provider.go
@@ -0,0 +1,50 @@
+package applicationservice
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+)
+
+// providerService holds methods to provider application service
+type providerService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+}
+
+// newProviderService returns a providerService instance
+func newProviderService(svc *service.Service, mapper *entitymapping.Mapper) *providerService {
+ return &providerService{
+ svc: svc,
+ mapEntity: mapper,
+ }
+}
+
+func (s *providerService) Save(providers []npdmodel.ProviderResponse, user viewmodel.User) ([]viewmodel.ProviderResp, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ entities := s.mapEntity.Provider.ToProviderEntitySlice(providers)
+ result, err := s.svc.Provider.Save(entities, eUser)
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Provider.ToProviderRespModelSlice(result), nil
+}
+
+func (s *providerService) GetAll(user viewmodel.User) ([]viewmodel.ProviderResp, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ providers, err := s.svc.Provider.GetAll(eUser)
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Provider.ToProviderRespModelSlice(providers), nil
+}
+
+func (s *providerService) Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user viewmodel.User) ([]viewmodel.ProviderResp, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ providers, err := s.svc.Provider.Get(query, lat, long, distance, planCode, productID, mukID, internalID, sort, eUser)
+ if err != nil {
+ return nil, err
+ }
+ return s.mapEntity.Provider.ToProviderRespModelSlice(providers), nil
+}
diff --git a/application/applicationservice/ride.go b/application/applicationservice/ride.go
new file mode 100644
index 0000000..1ecbabe
--- /dev/null
+++ b/application/applicationservice/ride.go
@@ -0,0 +1,420 @@
+package applicationservice
+
+import (
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+// rideService holds methods to user application service
+type rideService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+}
+
+// newUserService returns a userService instance
+func newRideService(svc *service.Service, mapper *entitymapping.Mapper) *rideService {
+ return &rideService{
+ svc: svc,
+ mapEntity: mapper,
+ }
+}
+
+func (s *rideService) UpdateNewRide(ride viewmodel.Ride, lyftRide viewmodel.RideRequest, user viewmodel.User) (viewmodel.Ride, error) {
+ webhookModel := viewmodel.WebhookResponse{
+ Ride: ride,
+ Event: lyftRide,
+ }
+ webhook := s.mapEntity.Ride.ToWebhookEntity(webhookModel)
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ oldRide, err := s.svc.Rides.GetByUUID(ride.UUID, eUser)
+ if err != nil {
+ return viewmodel.Ride{}, err
+ }
+
+ requestMS := (oldRide.PickupTime.UnixNano() / int64(time.Millisecond))
+ generateDate := time.Now()
+ generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
+ if webhook.Ride.RequestDate == nil {
+ webhook.Ride.RequestDate = oldRide.PickupTime
+ }
+ if webhook.Ride.RequestMiliseconds == nil {
+ webhook.Ride.RequestMiliseconds = &requestMS
+ }
+ if webhook.Ride.GenerateDate == nil {
+ webhook.Ride.GenerateDate = &generateDate
+ }
+ if webhook.Ride.GenerateMiliseconds == nil {
+ webhook.Ride.GenerateMiliseconds = &generateMS
+ }
+
+ switch webhook.Ride.Status.Key {
+ case "scheduled":
+ webhook.Ride.Route.ETA = oldRide.PickupTime.UnixNano() / int64(time.Second)
+ case "accepted":
+ if lyftRide.Origin.ETASeconds != nil {
+ webhook.Ride.Route.ETA = *lyftRide.Origin.ETASeconds
+ } else {
+ webhook.Ride.Route.ETA = 0
+ }
+ case "arrived", "pickedUp":
+ if lyftRide.Destination.ETASeconds != nil {
+ webhook.Ride.Route.ETA = *lyftRide.Destination.ETASeconds
+ } else {
+ webhook.Ride.Route.ETA = 0
+ }
+ case "droppedOff":
+ webhook.Ride.Route.ETA = 0
+ }
+ webhook.Ride.Route.Duration = int64(time.Now().Sub(*oldRide.PickupTime).Seconds())
+
+ webhook.Ride.InternalID = lyftRide.RideID
+ webhook.Ride.ID = oldRide.ID
+ webhook.Ride.UUID = oldRide.UUID
+ webhook.Ride.Driver.ID = oldRide.Driver.ID
+ webhook.Ride.Passenger.ID = oldRide.Passenger.ID
+ webhook.Ride.Route.ID = oldRide.Route.ID
+ webhook.Ride.Type.ID = oldRide.Type.ID
+ webhook.Ride.User = oldRide.User
+ webhook.Ride.CreatedUser = oldRide.CreatedUser
+ webhook.Ride.Vehicle.ID = oldRide.Vehicle.ID
+ webhook.Ride.Visit = oldRide.Visit
+ webhook.Ride.VisitDate = oldRide.VisitDate
+ webhook.Ride.VisitTime = oldRide.VisitTime
+ //webhook.Ride.PickupTime = oldRide.PickupTime
+
+ entityRide, err := s.svc.Rides.Update(webhook)
+ if err != nil {
+ return viewmodel.Ride{}, err
+ }
+
+ return s.mapEntity.Ride.ToRideModel(entityRide), nil
+}
+
+func (s *rideService) Update(ride viewmodel.WebhookResponse) (viewmodel.Ride, error) {
+ webhook := s.mapEntity.Ride.ToWebhookEntity(ride)
+ oldRide, err := s.svc.Rides.GetByInternalID(ride.Event.RideID)
+ if err != nil {
+ oldRide, err = s.svc.Rides.GetByInternalPassengerID(*ride.Event.Passenger.UserID)
+ if err != nil {
+ return viewmodel.Ride{}, err
+ }
+ }
+
+ requestMS := (oldRide.PickupTime.UnixNano() / int64(time.Millisecond))
+ generateDate := time.Now()
+ generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
+ if webhook.Ride.RequestDate == nil {
+ webhook.Ride.RequestDate = oldRide.PickupTime
+ }
+ if webhook.Ride.RequestMiliseconds == nil {
+ webhook.Ride.RequestMiliseconds = &requestMS
+ }
+ if webhook.Ride.GenerateDate == nil {
+ webhook.Ride.GenerateDate = &generateDate
+ }
+ if webhook.Ride.GenerateMiliseconds == nil {
+ webhook.Ride.GenerateMiliseconds = &generateMS
+ }
+
+ switch webhook.Ride.Status.Key {
+ case "scheduled":
+ webhook.Ride.Route.ETA = oldRide.PickupTime.UnixNano() / int64(time.Second)
+ case "accepted":
+ if ride.Event.Origin.ETASeconds != nil {
+ webhook.Ride.Route.ETA = *ride.Event.Origin.ETASeconds
+ } else {
+ webhook.Ride.Route.ETA = 0
+ }
+ case "arrived", "pickedUp":
+ if ride.Event.Destination.ETASeconds != nil {
+ webhook.Ride.Route.ETA = *ride.Event.Destination.ETASeconds
+ } else {
+ webhook.Ride.Route.ETA = 0
+ }
+ case "droppedOff":
+ webhook.Ride.Route.ETA = 0
+ }
+ webhook.Ride.Route.Duration = int64(time.Now().Sub(*oldRide.PickupTime).Seconds())
+
+ webhook.Ride.InternalID = ride.Event.RideID
+ webhook.Ride.ID = oldRide.ID
+ webhook.Ride.UUID = oldRide.UUID
+ webhook.Ride.Driver.ID = oldRide.Driver.ID
+ webhook.Ride.Passenger.ID = oldRide.Passenger.ID
+ webhook.Ride.Route.ID = oldRide.Route.ID
+ webhook.Ride.Type.ID = oldRide.Type.ID
+ webhook.Ride.User = oldRide.User
+ webhook.Ride.CreatedUser = oldRide.CreatedUser
+ webhook.Ride.Vehicle.ID = oldRide.Vehicle.ID
+ webhook.Ride.Visit = oldRide.Visit
+ webhook.Ride.VisitDate = oldRide.VisitDate
+ webhook.Ride.VisitTime = oldRide.VisitTime
+ webhook.Ride.PickupTime = oldRide.PickupTime
+
+ entityRide, err := s.svc.Rides.Update(webhook)
+ if err != nil {
+ return viewmodel.Ride{}, err
+ }
+
+ return s.mapEntity.Ride.ToRideModel(entityRide), nil
+}
+
+// Save a new ride
+func (s *rideService) Save(ride viewmodel.RideRequest) (viewmodel.Ride, error) {
+ rideEntity := s.mapEntity.Ride.ToRideEntity(ride)
+
+ if ride.Visit.UUID == "" {
+ visit := entity.Visit{}
+ visit.User = rideEntity.User
+ visit.Pickup = rideEntity.Route.Origin
+ visit.Notes = &rideEntity.Note
+ visit.PickupDatetime = *rideEntity.PickupTime
+ visit.VisitDatetime = *rideEntity.VisitTime
+ visit.CreatedUser.UUID = ride.CreateUserUUID
+ visit.ExternalID = ride.VisitExternalID
+ visit.TripType = rideEntity.Visit.TripType
+ visit.ReturnDate = ride.ReturnTime
+
+ address, _ := s.svc.Users.GetAddressByUUID(rideEntity.Route.Destination.ID)
+ createdUser, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ if address.ID > 0 {
+ visit.DestinationAddressID = address.ID
+ provider, err := s.svc.Provider.GetByMukID(address.InternalID, createdUser)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ visit.Provider = provider
+ } else {
+ provider, err := s.svc.Provider.GetByMukID(rideEntity.Route.Destination.ID, createdUser)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ visit.Provider = provider
+ }
+
+ visit, err = s.svc.Visits.Create(visit)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ rideEntity.Visit = visit
+ } else {
+ user, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ visit, err := s.svc.Visits.GetByUUID(ride.Visit.UUID, user)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ rideEntity.Visit = visit
+ }
+
+ retVal, err := s.svc.Rides.Save(rideEntity)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Ride.ToRideModel(retVal), err
+}
+
+// GetAll returns a list of users
+func (s *rideService) GetAll(user viewmodel.User) ([]viewmodel.Ride, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Rides.GetAll(eUser)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Ride.ToRideModelSlice(retVal), err
+}
+
+// GetByUUID returns a specific Ride
+func (s *rideService) GetByUUID(uuid string, user viewmodel.User) (viewmodel.Ride, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Rides.GetByUUID(uuid, eUser)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ if retVal.Visit.ID > 0 {
+ retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, eUser)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ }
+
+ return s.mapEntity.Ride.ToRideModel(retVal), err
+}
+
+func (s *rideService) GetByVisitUUID(visitUUID string, user viewmodel.User) ([]viewmodel.Ride, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Rides.GetByVisitUUID(visitUUID, eUser)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ visit, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ for i, _ := range retVal {
+ retVal[i].Visit = visit
+ }
+
+ return s.mapEntity.Ride.ToRideModelSlice(retVal), err
+}
+
+func (s *rideService) GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user viewmodel.User) (viewmodel.Ride, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Rides.GetByVisitUUIDAndTripType(visitUUID, tripTypeKey, eUser)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ visit, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ retVal.Visit = visit
+ return s.mapEntity.Ride.ToRideModel(retVal), err
+}
+
+// GetByUUID returns a specific Ride
+func (s *rideService) GetByUUIDAndUserUUID(uuid string, user_uuid string) (viewmodel.Ride, error) {
+ retVal, err := s.svc.Rides.GetByUUIDAndUserUUID(uuid, user_uuid)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ if retVal.Visit.ID > 0 {
+ user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ }
+
+ return s.mapEntity.Ride.ToRideModel(retVal), err
+}
+
+// GetByInternalID returns a specific Ride
+func (s *rideService) GetByInternalID(internalID string) (viewmodel.Ride, error) {
+ retVal, err := s.svc.Rides.GetByInternalID(internalID)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ if retVal.Visit.ID > 0 {
+ user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ }
+ return s.mapEntity.Ride.ToRideModel(retVal), err
+}
+
+// GetByUserID returns a list of rides for an user
+func (s *rideService) GetByUserID(userID int64, user viewmodel.User) ([]viewmodel.Ride, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Rides.GetByUserID(userID, eUser)
+ if err != nil {
+ return []viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Ride.ToRideModelSlice(retVal), err
+}
+
+// UpdateStatus change the status of the ride
+func (s *rideService) UpdateStatus(rideUUID string, status string) error {
+ err := s.svc.Rides.UpdateStatus(rideUUID, status)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
+
+// GetByUserID returns a list of rides for an user
+func (s *rideService) GetByUserUUID(userUUID string, user viewmodel.User) ([]viewmodel.Ride, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Rides.GetByUserUUID(userUUID, eUser)
+ if err != nil {
+ return []viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Ride.ToRideModelSlice(retVal), err
+}
+
+func (s *rideService) GetLastRideByPhoneNumber(phoneNumber string, notificationType string, status string) (viewmodel.Ride, error) {
+ // if notificationType == ""{
+ // notificationType = "message"
+ // }
+
+ if status == "" {
+ status = "sms"
+ }
+
+ notification, err := s.svc.Notification.GetLastNotificationFromPhoneNumber(notificationType, phoneNumber, status)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ user, err := s.svc.Users.GetByID(notification.CreatedUser.ID)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ retVal, err := s.svc.Rides.GetByID(notification.Ride.ID, user)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ if retVal.Visit.ID > 0 {
+ retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ }
+ return s.mapEntity.Ride.ToRideModel(retVal), err
+}
+
+func (s *rideService) GetLastRideByDriversNumber(phoneNumber string) (viewmodel.Ride, error) {
+ retVal, err := s.svc.Rides.GetLastRideByDriversNumber(phoneNumber)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ if retVal.Visit.ID > 0 {
+ user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+
+ retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
+ if err != nil {
+ return viewmodel.Ride{}, errors.Wrap(err)
+ }
+ }
+ return s.mapEntity.Ride.ToRideModel(retVal), err
+}
diff --git a/application/applicationservice/user.go b/application/applicationservice/user.go
new file mode 100644
index 0000000..0c9224b
--- /dev/null
+++ b/application/applicationservice/user.go
@@ -0,0 +1,149 @@
+package applicationservice
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+// userService holds methods to user application service
+type userService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+}
+
+// newUserService returns a userService instance
+func newUserService(svc *service.Service, mapper *entitymapping.Mapper) *userService {
+ return &userService{
+ svc: svc,
+ mapEntity: mapper,
+ }
+}
+
+// GetAll returns a list of users
+func (s *userService) GetAll(quantity int64, page int64) (retVal []viewmodel.User, err error) {
+ users, err := s.svc.Users.GetAll()
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+ return s.mapEntity.User.ToUserModelSlice(users), nil
+}
+
+// GetByID returns a specific user by its ID
+func (s *userService) GetByID(id int64) (retVal viewmodel.User, err error) {
+ user, err := s.svc.Users.GetByID(id)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ return s.mapEntity.User.ToUserModel(user), nil
+}
+
+// GetByID returns a specific user by its ID
+func (s *userService) GetByUUID(uuid string, profile string) (retVal viewmodel.User, err error) {
+ user, err := s.svc.Users.GetByUUID(uuid, profile)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ return s.mapEntity.User.ToUserModel(user), nil
+}
+
+// Login returns a specific user by email and pass
+func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (retVal viewmodel.User, err error) {
+ user, err := s.svc.Users.FullLogin(loginType, key, pass, profile)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ return s.mapEntity.User.ToUserModel(user), nil
+}
+
+// Login returns a specific user by email and pass
+func (s *userService) Login(email string, pass string) (retVal viewmodel.User, err error) {
+ user, err := s.svc.Users.Login(email, pass)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ return s.mapEntity.User.ToUserModel(user), nil
+}
+
+func (s *userService) Create(user viewmodel.User) (retVal viewmodel.User, err error) {
+ entity := s.mapEntity.User.ToUserEntity(user)
+
+ for i, _ := range entity.Organizations {
+ entity.Organizations[i], err = s.svc.Organization.GetByUUID(entity.Organizations[i].UUID)
+ if err != nil {
+ return retVal, err
+ }
+ }
+
+ entity, err = s.svc.Users.Create(entity)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ return s.mapEntity.User.ToUserModel(entity), nil
+}
+
+func (s *userService) CreateBulk(users []viewmodel.User) (retVal []viewmodel.User, err error) {
+ entities := s.mapEntity.User.ToUserEntitySlice(users)
+ organizations := make([]entity.Organization, 0)
+ for i, _ := range entities {
+ if i == 0 {
+ for o, _ := range entities[i].Organizations {
+ org, err := s.svc.Organization.GetByUUID(entities[i].Organizations[o].UUID)
+ if err != nil {
+ return nil, err
+ }
+ organizations = append(organizations, org)
+ }
+ }
+ entities[i].Organizations = organizations
+ }
+
+ entities, err = s.svc.Users.CreateBulk(entities)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ return s.mapEntity.User.ToUserModelSlice(entities), nil
+}
+
+// GetUsersByProfile returns a list of users by profile
+func (s *userService) GetUsersByProfile(profile string) (retVal []viewmodel.User, err error) {
+ users, err := s.svc.Users.GetUsersByProfile(profile)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ list := s.mapEntity.User.ToUserModelSlice(users)
+
+ return list, nil
+}
+
+func (s *userService) RemoveAddress(addressUUID string) error {
+ return s.svc.Users.RemoveAddress(addressUUID)
+}
+
+func (s *userService) SaveAddress(address viewmodel.Address) (retVal viewmodel.Address, err error) {
+ entity := s.mapEntity.Address.ToAddressEntity(address)
+ entity, err = s.svc.Users.SaveAddress(entity)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Address.ToAddressModel(entity), err
+}
+
+func (s *userService) GetContactType() (retVal []viewmodel.ContactType, err error) {
+ entity, err := s.svc.Users.GetContactType()
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+
+ return s.mapEntity.User.ToContactTypeModelSlice(entity), nil
+}
diff --git a/application/applicationservice/util.go b/application/applicationservice/util.go
new file mode 100644
index 0000000..1f48f8a
--- /dev/null
+++ b/application/applicationservice/util.go
@@ -0,0 +1,38 @@
+package applicationservice
+
+import (
+ "math"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+)
+
+// getTakeSkipPaging return the take and skip from page number and item quantity
+func getTakeSkipPaging(quantity int64, page int64) (take int64, skip int64) {
+ if page < 1 {
+ page = 1
+ }
+
+ if quantity < 1 {
+ quantity = 10
+ } else if quantity > 1000 {
+ quantity = 1000
+ }
+
+ take = quantity // itens per page
+ skip = (page - 1) * quantity
+
+ return take, skip
+}
+
+// buildPaginatedResult returns a paginatedResult instance
+func buildPaginatedResult(list interface{}, skip int64, take int64, totalRecords int64) viewmodel.PaginatedResult {
+ return viewmodel.PaginatedResult{
+ List: list,
+ Pagination: viewmodel.ReturnPagination{
+ CurrentPage: (skip / take) + 1,
+ RecordsPerPage: take,
+ TotalRecords: totalRecords,
+ TotalPages: int64(math.Ceil(float64(totalRecords) / float64(take))),
+ },
+ }
+}
diff --git a/application/applicationservice/visit.go b/application/applicationservice/visit.go
new file mode 100644
index 0000000..e3e0235
--- /dev/null
+++ b/application/applicationservice/visit.go
@@ -0,0 +1,55 @@
+package applicationservice
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+// rideService holds methods to user application service
+type visitService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+}
+
+// newUserService returns a userService instance
+func newVisitService(svc *service.Service, mapper *entitymapping.Mapper) *visitService {
+ return &visitService{
+ svc: svc,
+ mapEntity: mapper,
+ }
+}
+
+// Save a new ride
+func (s *visitService) Create(visit viewmodel.Visit) (viewmodel.Visit, error) {
+ entity := s.mapEntity.Visit.ToVisitEntity(visit)
+ retVal, err := s.svc.Visits.Create(entity)
+ if err != nil {
+ return viewmodel.Visit{}, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Visit.ToVisitModel(retVal), err
+}
+
+// Save a new ride
+func (s *visitService) GetAll(user viewmodel.User) ([]viewmodel.Visit, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Visits.GetAll(eUser)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Visit.ToVisitModelSlice(retVal), err
+}
+
+// Save a new ride
+func (s *visitService) GetByUUID(visitUUID string, user viewmodel.User) (viewmodel.Visit, error) {
+ eUser := s.mapEntity.User.ToUserEntity(user)
+ retVal, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
+ if err != nil {
+ return viewmodel.Visit{}, errors.Wrap(err)
+ }
+
+ return s.mapEntity.Visit.ToVisitModel(retVal), err
+}
diff --git a/application/entitymapping/address.go b/application/entitymapping/address.go
new file mode 100644
index 0000000..2371937
--- /dev/null
+++ b/application/entitymapping/address.go
@@ -0,0 +1,74 @@
+package entitymapping
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// rideMapping has method to map ride entities to view models
+type addressMapping struct {
+ mapper *Mapper
+}
+
+// ToVisitEntity maps a User entity to User view model
+func (mapping *addressMapping) ToAddressEntity(item viewmodel.Address) entity.Address {
+ return entity.Address{
+ UUID: item.UUID,
+ InternalID: item.InternalID,
+ Name: item.Name,
+ Address: item.Address,
+ AddressType: mapping.ToParamEntity(item.AddressType),
+ Latitude: item.Latitude,
+ Longitude: item.Longitude,
+ Origin: mapping.ToParamEntity(item.Type),
+ User: mapping.mapper.User.ToUserEntity(item.User),
+ CreatedUser: entity.User{
+ UUID: item.CreatedUserUUID,
+ },
+ }
+}
+
+func (mapping *addressMapping) ToParamEntity(item string) entity.Params {
+ return entity.Params{
+ Key: item,
+ }
+}
+
+// ToVisitEntity maps a User entity to User view model
+func (mapping *addressMapping) ToAddressModel(item entity.Address) viewmodel.Address {
+ return viewmodel.Address{
+ UUID: item.UUID,
+ InternalID: item.InternalID,
+ Name: item.Name,
+ Address: item.Address,
+ AddressType: item.AddressType.Key,
+ AddressTypeName: item.AddressType.Name,
+ Latitude: item.Latitude,
+ Longitude: item.Longitude,
+ Type: item.Origin.Key,
+ User: mapping.mapper.User.ToUserModel(item.User),
+ CreatedUserUUID: item.CreatedUser.UUID,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *addressMapping) ToAddressEntitySlice(list []viewmodel.Address) (retVal []entity.Address) {
+ retVal = make([]entity.Address, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToAddressEntity(item))
+ }
+
+ return retVal
+}
+
+// ToRideModelSlice maps a Ride entity slice to Ride view model slice
+func (mapping *addressMapping) ToAddressModelSlice(list []entity.Address) (retVal []viewmodel.Address) {
+ retVal = make([]viewmodel.Address, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToAddressModel(item))
+ }
+
+ return retVal
+}
diff --git a/application/entitymapping/entitymapping.go b/application/entitymapping/entitymapping.go
new file mode 100644
index 0000000..2c34565
--- /dev/null
+++ b/application/entitymapping/entitymapping.go
@@ -0,0 +1,51 @@
+package entitymapping
+
+import (
+ "strings"
+
+ "sync"
+)
+
+var (
+ instance *Mapper
+ once sync.Once
+)
+
+// Mapper has mapping methods to map entities to view models
+type Mapper struct {
+ User *userMapping
+ Ride *rideMapping
+ Visit *visitMapping
+ Address *addressMapping
+ Provider *providerMapping
+ Notification *notificationMapping
+ Profile *profileMapping
+ Organization *organizationMapping
+}
+
+// New returns an EntityMapper for fluent mapping
+func New() *Mapper {
+ once.Do(func() {
+ instance = &Mapper{}
+
+ instance.User = &userMapping{instance}
+ instance.Ride = &rideMapping{instance}
+ instance.Visit = &visitMapping{instance}
+ instance.Address = &addressMapping{instance}
+ instance.Provider = &providerMapping{instance}
+ instance.Notification = ¬ificationMapping{instance}
+ instance.Profile = &profileMapping{instance}
+ instance.Organization = &organizationMapping{instance}
+ })
+
+ return instance
+}
+
+// isEmpty returns the alternative option in case the first is empty
+func ifEmpty(firstOption string, alternativeOption string) string {
+ if strings.TrimSpace(firstOption) == "" {
+ return alternativeOption
+ }
+
+ return firstOption
+}
diff --git a/application/entitymapping/notification.go b/application/entitymapping/notification.go
new file mode 100644
index 0000000..11ef5da
--- /dev/null
+++ b/application/entitymapping/notification.go
@@ -0,0 +1,69 @@
+package entitymapping
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// providerMapping has method to map provider entities to view models
+type notificationMapping struct {
+ mapper *Mapper
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *notificationMapping) ToNotificationEntitySlice(list []viewmodel.Notification) (retVal []entity.Notification) {
+ retVal = make([]entity.Notification, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToNotificationEntity(item))
+ }
+
+ return retVal
+}
+
+func (mapping *notificationMapping) ToNotificationEntity(model viewmodel.Notification) entity.Notification {
+ return entity.Notification{
+ UUID: model.UUID,
+ To: model.To,
+ From: model.From,
+ Type: model.Type,
+ Subject: model.Subject,
+ Message: model.Message,
+ Created: model.Created,
+ Ride: entity.Ride{
+ UUID: model.Ride.UUID,
+ },
+ User: mapping.mapper.User.ToUserEntity(model.User),
+ CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
+ Read: model.Read,
+ MessageType: model.MessageType,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *notificationMapping) ToNotificationModelSlice(list []entity.Notification) (retVal []viewmodel.Notification) {
+ retVal = make([]viewmodel.Notification, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToNotificationModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *notificationMapping) ToNotificationModel(model entity.Notification) viewmodel.Notification {
+ return viewmodel.Notification{
+ UUID: model.UUID,
+ To: model.To,
+ From: model.From,
+ Type: model.Type,
+ Subject: model.Subject,
+ Message: model.Message,
+ Created: model.Created,
+ Ride: mapping.mapper.Ride.ToRideModel(model.Ride),
+ User: mapping.mapper.User.ToUserModel(model.User),
+ CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
+ Read: model.Read,
+ MessageType: model.MessageType,
+ }
+}
diff --git a/application/entitymapping/organization.go b/application/entitymapping/organization.go
new file mode 100644
index 0000000..8b0c7bd
--- /dev/null
+++ b/application/entitymapping/organization.go
@@ -0,0 +1,256 @@
+package entitymapping
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// providerMapping has method to map provider entities to view models
+type organizationMapping struct {
+ mapper *Mapper
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *organizationMapping) ToOrganizationTypeEntitySlice(list []viewmodel.OrganizationType) (retVal []entity.OrganizationType) {
+ retVal = make([]entity.OrganizationType, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationTypeEntity(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *organizationMapping) ToOrganizationEntitySlice(list []viewmodel.Organization) (retVal []entity.Organization) {
+ retVal = make([]entity.Organization, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationEntity(item))
+ }
+
+ return retVal
+}
+
+func (mapping *organizationMapping) ToOrganizationEntity(model viewmodel.Organization) entity.Organization {
+ return entity.Organization{
+ ID: model.ID,
+ UUID: model.UUID,
+ Type: mapping.ToOrganizationTypeEntity(model.Type),
+ Name: model.Name,
+ Description: model.Description,
+ ReferenceID: model.ReferenceID,
+ ParentID: model.ParentID,
+ Main: model.Main,
+ Created: model.Created,
+ Updated: model.Updated,
+ Active: model.Active,
+ Blocked: model.Blocked,
+ Suspended: model.Suspended,
+ Author: mapping.mapper.User.ToUserEntity(model.Author),
+ LastEditor: mapping.mapper.User.ToUserEntity(model.LastEditor),
+ Contacts: mapping.ToOrganizationContactEntitySlice(model.Contacts),
+ Addresses: mapping.ToOrganizationAddressEntitySlice(model.Addresses),
+ ChildOrgs: mapping.ToOrganizationEntitySlice(model.ChildOrgs),
+ Parent: mapping.ToOrganizationEntityPointer(model.Parent),
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationEntityPointer(model *viewmodel.Organization) *entity.Organization {
+ if model != nil {
+ convertibleModel := *model
+ convertibleEntity := mapping.ToOrganizationEntity(convertibleModel)
+ return &convertibleEntity
+ } else {
+ return nil
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationModelPointer(model *entity.Organization) *viewmodel.Organization {
+ if model != nil {
+ convertibleModel := *model
+ convertibleEntity := mapping.ToOrganizationModel(convertibleModel)
+ return &convertibleEntity
+ } else {
+ return nil
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationTypeEntity(model viewmodel.OrganizationType) entity.OrganizationType {
+ return entity.OrganizationType{
+ ID: model.ID,
+ Name: model.Name,
+ Key: model.Key,
+ Description: model.Description,
+ Created: model.Created,
+ Updated: model.Updated,
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationTypeModelSlice(list []entity.OrganizationType) (retVal []viewmodel.OrganizationType) {
+ retVal = make([]viewmodel.OrganizationType, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationTypeModel(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *organizationMapping) ToOrganizationModelSlice(list []entity.Organization) (retVal []viewmodel.Organization) {
+ retVal = make([]viewmodel.Organization, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *organizationMapping) ToOrganizationModel(model entity.Organization) viewmodel.Organization {
+ return viewmodel.Organization{
+ ID: model.ID,
+ UUID: model.UUID,
+ Type: mapping.ToOrganizationTypeModel(model.Type),
+ Name: model.Name,
+ Description: model.Description,
+ ReferenceID: model.ReferenceID,
+ ParentID: model.ParentID,
+ Main: model.Main,
+ Created: model.Created,
+ Updated: model.Updated,
+ Active: model.Active,
+ Blocked: model.Blocked,
+ Suspended: model.Suspended,
+ Author: mapping.mapper.User.ToUserModel(model.Author),
+ LastEditor: mapping.mapper.User.ToUserModel(model.LastEditor),
+ Contacts: mapping.ToOrganizationContactModelSlice(model.Contacts),
+ Addresses: mapping.ToOrganizationAddressModelSlice(model.Addresses),
+ ChildOrgs: mapping.ToOrganizationModelSlice(model.ChildOrgs),
+ Parent: mapping.ToOrganizationModelPointer(model.Parent),
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationTypeModel(model entity.OrganizationType) viewmodel.OrganizationType {
+ return viewmodel.OrganizationType{
+ ID: model.ID,
+ Name: model.Name,
+ Key: model.Key,
+ Description: model.Description,
+ Created: model.Created,
+ Updated: model.Updated,
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationContactModel(model entity.OrganizationContact) viewmodel.OrganizationContact {
+ return viewmodel.OrganizationContact{
+ ID: model.ID,
+ UUID: model.UUID,
+ Type: mapping.mapper.User.ToContactTypeModel(model.Type),
+ Contact: model.Contact,
+ Name: model.Name,
+ Description: model.Description,
+ Created: model.Created,
+ CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
+ Updated: model.Updated,
+ UpdatedUser: mapping.mapper.User.ToUserModel(model.UpdatedUser),
+ Active: model.Active,
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationContactEntity(model viewmodel.OrganizationContact) entity.OrganizationContact {
+ return entity.OrganizationContact{
+ ID: model.ID,
+ UUID: model.UUID,
+ Type: mapping.mapper.User.ToContactTypeEntity(model.Type),
+ Contact: model.Contact,
+ Name: model.Name,
+ Description: model.Description,
+ Created: model.Created,
+ CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
+ Updated: model.Updated,
+ UpdatedUser: mapping.mapper.User.ToUserEntity(model.UpdatedUser),
+ Active: model.Active,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *organizationMapping) ToOrganizationContactModelSlice(list []entity.OrganizationContact) (retVal []viewmodel.OrganizationContact) {
+ retVal = make([]viewmodel.OrganizationContact, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationContactModel(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *organizationMapping) ToOrganizationContactEntitySlice(list []viewmodel.OrganizationContact) (retVal []entity.OrganizationContact) {
+ retVal = make([]entity.OrganizationContact, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationContactEntity(item))
+ }
+
+ return retVal
+}
+
+func (mapping *organizationMapping) ToOrganizationAddressModel(model entity.OrganizationAddress) viewmodel.OrganizationAddress {
+ return viewmodel.OrganizationAddress{
+ ID: model.ID,
+ UUID: model.UUID,
+ InternalID: model.InternalID,
+ Address: model.Address,
+ Name: model.Name,
+ Description: model.Description,
+ Latitude: model.Latitude,
+ Longitude: model.Longitude,
+ Created: model.Created,
+ CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
+ Updated: model.Updated,
+ UpdatedUser: mapping.mapper.User.ToUserModel(model.UpdatedUser),
+ Active: model.Active,
+ }
+}
+
+func (mapping *organizationMapping) ToOrganizationAddressEntity(model viewmodel.OrganizationAddress) entity.OrganizationAddress {
+ return entity.OrganizationAddress{
+ ID: model.ID,
+ UUID: model.UUID,
+ InternalID: model.InternalID,
+ Address: model.Address,
+ Name: model.Name,
+ Description: model.Description,
+ Latitude: model.Latitude,
+ Longitude: model.Longitude,
+ Created: model.Created,
+ CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
+ Updated: model.Updated,
+ UpdatedUser: mapping.mapper.User.ToUserEntity(model.UpdatedUser),
+ Active: model.Active,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *organizationMapping) ToOrganizationAddressModelSlice(list []entity.OrganizationAddress) (retVal []viewmodel.OrganizationAddress) {
+ retVal = make([]viewmodel.OrganizationAddress, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationAddressModel(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *organizationMapping) ToOrganizationAddressEntitySlice(list []viewmodel.OrganizationAddress) (retVal []entity.OrganizationAddress) {
+ retVal = make([]entity.OrganizationAddress, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToOrganizationAddressEntity(item))
+ }
+
+ return retVal
+}
diff --git a/application/entitymapping/profile.go b/application/entitymapping/profile.go
new file mode 100644
index 0000000..bb3fef7
--- /dev/null
+++ b/application/entitymapping/profile.go
@@ -0,0 +1,65 @@
+package entitymapping
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// providerMapping has method to map provider entities to view models
+type profileMapping struct {
+ mapper *Mapper
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *profileMapping) ToProfileEntitySlice(list []viewmodel.Profile) (retVal []entity.Profile) {
+ retVal = make([]entity.Profile, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProfileEntity(item))
+ }
+
+ return retVal
+}
+
+func (mapping *profileMapping) ToProfileEntity(model viewmodel.Profile) entity.Profile {
+ return entity.Profile{
+ ID: model.ID,
+ Key: model.Key,
+ Name: model.Name,
+ Description: model.Description,
+ Created: model.Created,
+ Updated: model.Updated,
+ Active: model.Active,
+ Visible: model.Visible,
+ Blocked: model.Blocked,
+ Suspended: model.Suspended,
+ Organization: mapping.mapper.Organization.ToOrganizationEntity(model.Organization),
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *profileMapping) ToProfileModelSlice(list []entity.Profile) (retVal []viewmodel.Profile) {
+ retVal = make([]viewmodel.Profile, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProfileModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *profileMapping) ToProfileModel(model entity.Profile) viewmodel.Profile {
+ return viewmodel.Profile{
+ ID: model.ID,
+ Key: model.Key,
+ Name: model.Name,
+ Description: model.Description,
+ Created: model.Created,
+ Updated: model.Updated,
+ Active: model.Active,
+ Visible: model.Visible,
+ Blocked: model.Blocked,
+ Suspended: model.Suspended,
+ Organization: mapping.mapper.Organization.ToOrganizationModel(model.Organization),
+ }
+}
diff --git a/application/entitymapping/provider.go b/application/entitymapping/provider.go
new file mode 100644
index 0000000..059b9ba
--- /dev/null
+++ b/application/entitymapping/provider.go
@@ -0,0 +1,375 @@
+package entitymapping
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// providerMapping has method to map provider entities to view models
+type providerMapping struct {
+ mapper *Mapper
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToProviderRespEntitySlice(list []viewmodel.ProviderResp) (retVal []entity.Provider) {
+ retVal = make([]entity.Provider, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProviderRespEntity(item))
+ }
+
+ return retVal
+}
+
+func (mapping *providerMapping) ToProviderRespEntity(item viewmodel.ProviderResp) entity.Provider {
+ return entity.Provider{
+ ProviderUUID: item.ProviderUUID,
+ InternalID: item.InternalID,
+ InternalSuffixID: item.InternalSuffixID,
+ MukID: item.MukID,
+ OrganizatioName: item.OrganizatioName,
+ Gender: item.Gender,
+ AcceptNewPatients: item.AcceptNewPatients,
+ Name: item.Name,
+ FirstName: item.FirstName,
+ MiddleName: item.MiddleName,
+ LastName: item.LastName,
+ Title: item.Title,
+ Distance: item.Distance,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToProviderRespModelSlice(list []entity.Provider) (retVal []viewmodel.ProviderResp) {
+ retVal = make([]viewmodel.ProviderResp, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProviderRespModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *providerMapping) ToProviderRespModel(item entity.Provider) viewmodel.ProviderResp {
+ return viewmodel.ProviderResp{
+ ProviderUUID: item.ProviderUUID,
+ InternalID: item.InternalID,
+ InternalSuffixID: item.InternalSuffixID,
+ MukID: item.MukID,
+ OrganizatioName: item.OrganizatioName,
+ Gender: item.Gender,
+ AcceptNewPatients: item.AcceptNewPatients,
+ Name: item.Name,
+ FirstName: item.FirstName,
+ MiddleName: item.MiddleName,
+ LastName: item.LastName,
+ Title: item.Title,
+ Keys: mapping.ToProviderKeyModelSlice(item.Keys),
+ Address: mapping.ToProviderRespAddressModel(item.Address),
+ Distance: item.Distance,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToProviderKeyModelSlice(list []entity.ProviderKey) (retVal []viewmodel.ProviderKey) {
+ retVal = make([]viewmodel.ProviderKey, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProviderKeyModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *providerMapping) ToProviderKeyModel(item entity.ProviderKey) viewmodel.ProviderKey {
+ return viewmodel.ProviderKey{
+ InternalID: item.InternalID,
+ InternalSuffixID: item.InternalSuffixID,
+ LocationSeqNumber: item.LocationSeqNumber,
+ PlanCode: item.PlanCode,
+ ProductID: item.ProductID,
+ TreatmentCategoryCode: item.TreatmentCategoryCode,
+ }
+}
+
+func (mapping *providerMapping) ToProviderRespAddressModel(item entity.ProviderAddress) viewmodel.ProviderAddress {
+ return viewmodel.ProviderAddress{
+ StreetAddress1: item.StreetAddress1,
+ StreetAddress2: item.StreetAddress2,
+ CityName: item.CityName,
+ State: item.State,
+ ZipCode: item.ZipCode,
+ Country: item.Country,
+ Latitude: item.Latitude,
+ Longitude: item.Longitude,
+ PhoneNumber: item.PhoneNumber,
+ }
+}
+
+func (mapping *providerMapping) ToProviderEntity(item npdmodel.ProviderResponse) entity.ProviderResponse {
+ return entity.ProviderResponse{
+ MukID: item.MukID,
+ FivePartKeyGroups: mapping.ToPartKeyGroupEntitySlice(item.FivePartKeyGroups),
+ OrgName: item.OrgName,
+ Gender: item.Gender,
+ AcceptNewPatients: item.AcceptNewPatients,
+ ProviderName: item.ProviderName,
+ FirstName: item.FirstName,
+ LastName: item.LastName,
+ MiddleName: item.MiddleName,
+ ProviderTitle: item.ProviderTitle,
+ StreetName1: item.StreetName1,
+ StreetName2: item.StreetName2,
+ CityName: item.CityName,
+ State: item.State,
+ ZipCode: item.ZipCode,
+ Country: item.Country,
+ Latitude: item.Latitude,
+ Longitude: item.Longitude,
+ PhoneNumber: item.PhoneNumber,
+ ProviderEntityName: item.ProviderEntityName,
+ ProviderEntityCode: item.ProviderEntityCode,
+ ProviderTypeCode: mapping.ToProviderTypeCodeEntitySlice(item.ProviderTypeCode),
+ Distance: item.Distance,
+ AvailabilityOfCost: item.AvailabilityOfCost,
+ TDDPhoneNumber: item.TDDPhoneNumber,
+ ExtendedOfficeHours: item.ExtendedOfficeHours,
+ ProviderCountyCode: item.ProviderCountyCode,
+ ProviderCountyName: item.ProviderCountyName,
+ HospitalAffiliationNames: mapping.ToHospitalAffiliationNamesEntitySlice(item.HospitalAffiliationNames),
+ ProviderAffiliationNumber: item.ProviderAffiliationNumber,
+ ProviderAffiliationName: item.ProviderAffiliationName,
+ LanguagesSpoken: mapping.ToLanguagesEntitySlice(item.LanguagesSpoken),
+ OfficeLanguagesSpoken: mapping.ToLanguagesEntitySlice(item.OfficeLanguagesSpoken),
+ MedSchool: item.MedSchool,
+ MedSchoolYear: item.MedSchoolYear,
+ Internship: item.Internship,
+ Residence: item.Residence,
+ Specialty1: item.Specialty1,
+ Specialty2: item.Specialty2,
+ Specialty3: item.Specialty3,
+ Specialty4: item.Specialty4,
+ Certification1: item.Certification1,
+ Certification2: item.Certification2,
+ Certification3: item.Certification3,
+ Certification4: item.Certification4,
+ }
+}
+
+func (mapping *providerMapping) ToProviderModel(item entity.ProviderResponse) npdmodel.ProviderResponse {
+ return npdmodel.ProviderResponse{
+ MukID: item.MukID,
+ FivePartKeyGroups: mapping.ToPartKeyGroupModelSlice(item.FivePartKeyGroups),
+ OrgName: item.OrgName,
+ Gender: item.Gender,
+ AcceptNewPatients: item.AcceptNewPatients,
+ ProviderName: item.ProviderName,
+ FirstName: item.FirstName,
+ LastName: item.LastName,
+ MiddleName: item.MiddleName,
+ ProviderTitle: item.ProviderTitle,
+ StreetName1: item.StreetName1,
+ StreetName2: item.StreetName2,
+ CityName: item.CityName,
+ State: item.State,
+ ZipCode: item.ZipCode,
+ Country: item.Country,
+ Latitude: item.Latitude,
+ Longitude: item.Longitude,
+ PhoneNumber: item.PhoneNumber,
+ ProviderEntityName: item.ProviderEntityName,
+ ProviderEntityCode: item.ProviderEntityCode,
+ ProviderTypeCode: mapping.ToProviderTypeCodeModelSlice(item.ProviderTypeCode),
+ Distance: item.Distance,
+ AvailabilityOfCost: item.AvailabilityOfCost,
+ TDDPhoneNumber: item.TDDPhoneNumber,
+ ExtendedOfficeHours: item.ExtendedOfficeHours,
+ ProviderCountyCode: item.ProviderCountyCode,
+ ProviderCountyName: item.ProviderCountyName,
+ HospitalAffiliationNames: mapping.ToHospitalAffiliationNamesModelSlice(item.HospitalAffiliationNames),
+ ProviderAffiliationNumber: item.ProviderAffiliationNumber,
+ ProviderAffiliationName: item.ProviderAffiliationName,
+ LanguagesSpoken: mapping.ToLanguagesModelSlice(item.LanguagesSpoken),
+ OfficeLanguagesSpoken: mapping.ToLanguagesModelSlice(item.OfficeLanguagesSpoken),
+ MedSchool: item.MedSchool,
+ MedSchoolYear: item.MedSchoolYear,
+ Internship: item.Internship,
+ Residence: item.Residence,
+ Specialty1: item.Specialty1,
+ Specialty2: item.Specialty2,
+ Specialty3: item.Specialty3,
+ Specialty4: item.Specialty4,
+ Certification1: item.Certification1,
+ Certification2: item.Certification2,
+ Certification3: item.Certification3,
+ Certification4: item.Certification4}
+}
+
+func (mapping *providerMapping) ToHospitalAffiliationNamesEntity(item npdmodel.HospitalAffiliationNames) entity.HospitalAffiliationNames {
+ return entity.HospitalAffiliationNames{
+ HospAffProvOrgName: item.HospAffProvOrgName,
+ }
+}
+
+func (mapping *providerMapping) ToHospitalAffiliationNamesModel(item entity.HospitalAffiliationNames) npdmodel.HospitalAffiliationNames {
+ return npdmodel.HospitalAffiliationNames{
+ HospAffProvOrgName: item.HospAffProvOrgName,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToHospitalAffiliationNamesEntitySlice(list []npdmodel.HospitalAffiliationNames) (retVal []entity.HospitalAffiliationNames) {
+ retVal = make([]entity.HospitalAffiliationNames, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToHospitalAffiliationNamesEntity(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToHospitalAffiliationNamesModelSlice(list []entity.HospitalAffiliationNames) (retVal []npdmodel.HospitalAffiliationNames) {
+ retVal = make([]npdmodel.HospitalAffiliationNames, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToHospitalAffiliationNamesModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *providerMapping) ToLanguagesEntity(item npdmodel.Languages) entity.Languages {
+ return entity.Languages{
+ Code: item.Code,
+ }
+}
+
+func (mapping *providerMapping) ToLanguagesModel(item entity.Languages) npdmodel.Languages {
+ return npdmodel.Languages{
+ Code: item.Code,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToLanguagesEntitySlice(list []npdmodel.Languages) (retVal []entity.Languages) {
+ retVal = make([]entity.Languages, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToLanguagesEntity(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToLanguagesModelSlice(list []entity.Languages) (retVal []npdmodel.Languages) {
+ retVal = make([]npdmodel.Languages, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToLanguagesModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *providerMapping) ToProviderTypeCodeEntity(item npdmodel.ProviderTypeCode) entity.ProviderTypeCode {
+ return entity.ProviderTypeCode{
+ Code: item.Code,
+ }
+}
+
+func (mapping *providerMapping) ToProviderTypeCodeModel(item entity.ProviderTypeCode) npdmodel.ProviderTypeCode {
+ return npdmodel.ProviderTypeCode{
+ Code: item.Code,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToProviderTypeCodeEntitySlice(list []npdmodel.ProviderTypeCode) (retVal []entity.ProviderTypeCode) {
+ retVal = make([]entity.ProviderTypeCode, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProviderTypeCodeEntity(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToProviderTypeCodeModelSlice(list []entity.ProviderTypeCode) (retVal []npdmodel.ProviderTypeCode) {
+ retVal = make([]npdmodel.ProviderTypeCode, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProviderTypeCodeModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *providerMapping) ToPartKeyGroupEntity(item npdmodel.PartKeyGroup) entity.PartKeyGroup {
+ return entity.PartKeyGroup{
+ ProviderNum: item.ProviderNum,
+ ProviderNumSuffix: item.ProviderNumSuffix,
+ LocationSeqNum: item.LocationSeqNum,
+ PlanCode: item.PlanCode,
+ ProductID: item.ProductID,
+ TreatmentCategoryCode: item.TreatmentCategoryCode,
+ }
+}
+
+func (mapping *providerMapping) ToPartKeyGroupModel(item entity.PartKeyGroup) npdmodel.PartKeyGroup {
+ return npdmodel.PartKeyGroup{
+ ProviderNum: item.ProviderNum,
+ ProviderNumSuffix: item.ProviderNumSuffix,
+ LocationSeqNum: item.LocationSeqNum,
+ PlanCode: item.PlanCode,
+ ProductID: item.ProductID,
+ TreatmentCategoryCode: item.TreatmentCategoryCode,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToPartKeyGroupEntitySlice(list []npdmodel.PartKeyGroup) (retVal []entity.PartKeyGroup) {
+ retVal = make([]entity.PartKeyGroup, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToPartKeyGroupEntity(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToPartKeyGroupModelSlice(list []entity.PartKeyGroup) (retVal []npdmodel.PartKeyGroup) {
+ retVal = make([]npdmodel.PartKeyGroup, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToPartKeyGroupModel(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToProviderEntitySlice(list []npdmodel.ProviderResponse) (retVal []entity.ProviderResponse) {
+ retVal = make([]entity.ProviderResponse, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProviderEntity(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *providerMapping) ToProviderModelSlice(list []entity.ProviderResponse) (retVal []npdmodel.ProviderResponse) {
+ retVal = make([]npdmodel.ProviderResponse, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToProviderModel(item))
+ }
+
+ return retVal
+}
diff --git a/application/entitymapping/ride.go b/application/entitymapping/ride.go
new file mode 100644
index 0000000..e82b2b6
--- /dev/null
+++ b/application/entitymapping/ride.go
@@ -0,0 +1,254 @@
+package entitymapping
+
+import (
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// rideMapping has method to map ride entities to view models
+type rideMapping struct {
+ mapper *Mapper
+}
+
+func (mapping *rideMapping) ToRideModel(item entity.Ride) viewmodel.Ride {
+ return viewmodel.Ride{
+ User: mapping.mapper.User.ToUserModel(item.User),
+ Status: mapping.ToRideStatusModel(item.Status),
+ Type: mapping.ToRideTypeModel(item.Type),
+ UUID: item.UUID,
+ Note: item.Note,
+ Driver: mapping.ToDriverUserModel(item.Driver),
+ Passenger: mapping.ToPassengerUserModel(item.Passenger),
+ Vehicle: mapping.ToVehicleModel(item.Vehicle),
+ Route: mapping.ToRouteModel(item.Route),
+ PickupTime: item.PickupTime,
+ VisitDate: item.VisitDate,
+ VisitTime: item.VisitTime,
+ InternalID: item.InternalID,
+ Visit: mapping.mapper.Visit.ToVisitModel(item.Visit),
+ CreatedUser: mapping.mapper.User.ToUserModel(item.CreatedUser),
+ CreateAt: item.Created,
+ UpdateAt: item.Updated,
+ TripType: mapping.mapper.Visit.ToTripTypeModel(item.TripType),
+ }
+}
+
+func (mapping *rideMapping) ToRideInternalEntity(item viewmodel.Ride) entity.Ride {
+ return entity.Ride{
+ User: mapping.mapper.User.ToUserEntity(item.User),
+ UUID: item.UUID,
+ Note: item.Note,
+ PickupTime: item.PickupTime,
+ VisitDate: item.VisitDate,
+ VisitTime: item.VisitTime,
+ InternalID: item.InternalID,
+ TripType: mapping.mapper.Visit.ToTripTypeEntity(item.TripType),
+ }
+}
+
+func (mapping *rideMapping) ToRouteModel(item entity.RideRoute) viewmodel.RideRoute {
+ return viewmodel.RideRoute{
+ Origin: mapping.ToLocationModel(item.Origin),
+ Destination: mapping.ToLocationModel(item.Destination),
+ RouteKML: item.RouteKML,
+ ETA: item.ETA,
+ Distance: item.Distance,
+ Duration: item.Duration,
+ }
+}
+
+func (mapping *rideMapping) ToLocationModel(item entity.Location) viewmodel.Location {
+ return viewmodel.Location{
+ ID: item.ID,
+ Name: item.Name,
+ Address: item.Address,
+ Latitude: item.Latitude,
+ Longitude: item.Longitude,
+ }
+}
+
+func (mapping *rideMapping) ToVehicleModel(item entity.RideVehicle) viewmodel.Vehicle {
+ return viewmodel.Vehicle{
+ Color: item.Color,
+ Make: item.Make,
+ LicensePlate: item.LicensePlate,
+ ImageURL: item.ImageURL,
+ Year: item.Year,
+ LicensePlateState: item.LicensePlateState,
+ Model: item.Model,
+ }
+}
+
+func (mapping *rideMapping) ToDriverUserModel(item entity.RideDriver) viewmodel.UserLyft {
+ return viewmodel.UserLyft{
+ FirstName: item.Name,
+ ImageURL: item.ImageURL,
+ PhoneNumber: item.PhoneNumber,
+ Rating: item.Rating,
+ }
+}
+
+func (mapping *rideMapping) ToPassengerUserModel(item entity.RidePassenger) viewmodel.UserLyft {
+ return viewmodel.UserLyft{
+ FirstName: item.FirstName,
+ LastName: item.LastName,
+ ImageURL: item.ImageURL,
+ PhoneNumber: item.PhoneNumber,
+ UserID: item.InternalID,
+ }
+}
+
+func (mapping *rideMapping) ToRideStatusModel(item entity.RideStatus) viewmodel.RideStatus {
+ return viewmodel.RideStatus{
+ Value: item.Value,
+ Key: item.Key,
+ }
+}
+
+func (mapping *rideMapping) ToRideTypeModel(item entity.RideType) viewmodel.RideType {
+ return viewmodel.RideType{
+ Value: item.Value,
+ Key: item.Key,
+ }
+}
+
+func (mapping *rideMapping) ToWebhookEntity(item viewmodel.WebhookResponse) entity.WebhookResponse {
+ occurredAt, _ := time.Parse(time.RFC3339Nano, item.OccurredAt)
+
+ return entity.WebhookResponse{
+ EventID: item.EventID,
+ HREF: item.HREF,
+ OccurredAt: occurredAt,
+ EventType: item.EventType,
+ Ride: mapping.ToRideEntity(item.Event),
+ }
+}
+
+// ToUserModel maps a User entity to User view model
+func (mapping *rideMapping) ToRideEntity(item viewmodel.RideRequest) entity.Ride {
+ return entity.Ride{
+ User: entity.User{
+ UUID: item.UserUUID,
+ },
+ Status: mapping.ToRideStatusEntity(item),
+ Type: mapping.ToRideTypeEntity(item),
+ InternalID: item.RideID,
+ RequestDate: item.RequestAt,
+ RequestMiliseconds: item.RequestAtMS,
+ GenerateDate: item.GeneratedAt,
+ GenerateMiliseconds: item.GeneratedAtMS,
+ Note: item.Notes,
+ PrimetimePercentage: item.PrimetimePercentage,
+ Passenger: mapping.ToRidePassengerEntity(item),
+ Driver: mapping.ToRideDriverEntity(item),
+ Vehicle: mapping.ToRideVehicleEntity(item),
+ Route: mapping.ToRideRouteEntity(item),
+ PickupTime: item.PickupTime,
+ VisitDate: item.VisitDate,
+ VisitTime: item.VisitTime,
+ Visit: mapping.mapper.Visit.ToVisitEntity(item.Visit),
+ TripType: mapping.mapper.Visit.ToTripTypeEntity(item.TripType),
+ CreatedUser: entity.User{
+ UUID: item.CreateUserUUID,
+ },
+ }
+}
+
+func (mapping *rideMapping) ToRideRouteEntity(item viewmodel.RideRequest) entity.RideRoute {
+ return entity.RideRoute{
+ Origin: mapping.ToLocationEntity(item.Origin),
+ Destination: mapping.ToLocationEntity(item.Destination),
+ RouteKML: &item.RouteURL,
+ ETA: item.ETA,
+ Distance: item.Distance,
+ Duration: item.Duration,
+ }
+}
+
+func (mapping *rideMapping) ToLocationEntity(item viewmodel.Location) entity.Location {
+ return entity.Location{
+ ID: item.ID,
+ Name: item.Name,
+ Address: item.Address,
+ Latitude: item.Latitude,
+ Longitude: item.Longitude,
+ }
+}
+
+func (mapping *rideMapping) ToRideVehicleEntity(item viewmodel.RideRequest) entity.RideVehicle {
+ return entity.RideVehicle{
+ Color: item.Vehicle.Color,
+ Make: item.Vehicle.Make,
+ LicensePlate: item.Vehicle.LicensePlate,
+ LicensePlateState: item.Vehicle.LicensePlateState,
+ ImageURL: item.Vehicle.ImageURL,
+ Model: item.Vehicle.Model,
+ Year: item.Vehicle.Year,
+ }
+}
+
+func (mapping *rideMapping) ToRideDriverEntity(item viewmodel.RideRequest) entity.RideDriver {
+ return entity.RideDriver{
+ Name: item.Driver.FirstName,
+ ImageURL: item.Driver.ImageURL,
+ PhoneNumber: item.Driver.PhoneNumber,
+ Rating: item.Driver.Rating,
+ }
+}
+
+func (mapping *rideMapping) ToRidePassengerEntity(item viewmodel.RideRequest) entity.RidePassenger {
+ return entity.RidePassenger{
+ FirstName: item.Passenger.FirstName,
+ LastName: item.Passenger.LastName,
+ ImageURL: item.Passenger.ImageURL,
+ PhoneNumber: item.Passenger.PhoneNumber,
+ InternalID: item.Passenger.UserID,
+ }
+}
+
+func (mapping *rideMapping) ToRideStatusEntity(item viewmodel.RideRequest) entity.RideStatus {
+ return entity.RideStatus{
+ Key: item.Status,
+ }
+}
+
+func (mapping *rideMapping) ToRideTypeEntity(item viewmodel.RideRequest) entity.RideType {
+ return entity.RideType{
+ Key: item.RideType,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *rideMapping) ToRideEntitySlice(list []viewmodel.RideRequest) (retVal []entity.Ride) {
+ retVal = make([]entity.Ride, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToRideEntity(item))
+ }
+
+ return retVal
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *rideMapping) ToRideInternalEntitySlice(list []viewmodel.Ride) (retVal []entity.Ride) {
+ retVal = make([]entity.Ride, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToRideInternalEntity(item))
+ }
+
+ return retVal
+}
+
+// ToRideModelSlice maps a Ride entity slice to Ride view model slice
+func (mapping *rideMapping) ToRideModelSlice(list []entity.Ride) (retVal []viewmodel.Ride) {
+ retVal = make([]viewmodel.Ride, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToRideModel(item))
+ }
+
+ return retVal
+}
diff --git a/application/entitymapping/user.go b/application/entitymapping/user.go
new file mode 100644
index 0000000..a2c3473
--- /dev/null
+++ b/application/entitymapping/user.go
@@ -0,0 +1,194 @@
+package entitymapping
+
+import (
+ "fmt"
+ "strings"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// userMapping has method to map User entities to view models
+type userMapping struct {
+ mapper *Mapper
+}
+
+// ToUserModel maps a User entity to User view model
+func (mapping *userMapping) ToUserModel(item entity.User) viewmodel.User {
+ var birthDate *time.Time
+ if !item.BirthDate.IsZero() {
+ birthDate = &item.BirthDate
+ }
+
+ first := ""
+ last := ""
+ fullName := strings.Split(item.Name, " ")
+ if len(fullName) > 0 {
+ first = fullName[0]
+ if len(fullName) > 1 {
+ last = fullName[len(fullName)-1]
+ }
+ }
+
+ return viewmodel.User{
+ ID: item.UUID,
+ Name: item.Name,
+ First: first,
+ Last: last,
+ Email: &item.Email,
+ PhoneNumber: &item.PhoneNumber,
+ Gender: &item.Gender,
+ Member: &item.Member,
+ BirthDate: birthDate,
+ Active: item.Active,
+ Created: item.Created,
+ Updated: item.Updated,
+ Contacts: mapping.ToContactModelSlice(item.Contacts),
+ Rides: mapping.mapper.Ride.ToRideModelSlice(item.Rides),
+ Addresses: mapping.mapper.Address.ToAddressModelSlice(item.Addresses),
+ Profiles: mapping.mapper.Profile.ToProfileModelSlice(item.Profiles),
+ Organizations: mapping.mapper.Organization.ToOrganizationModelSlice(item.Organizations),
+ Types: mapping.mapper.Organization.ToOrganizationTypeModelSlice(item.Types),
+ }
+}
+
+// ToUserModelSlice maps a User entity slice to User view model slice
+func (mapping *userMapping) ToUserModelSlice(list []entity.User) (retVal []viewmodel.User) {
+ retVal = make([]viewmodel.User, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToUserModel(item))
+ }
+
+ return retVal
+}
+
+// ToUserModel maps a User entity to User view model
+func (mapping *userMapping) ToUserEntity(item viewmodel.User) entity.User {
+ user := entity.User{
+ UUID: item.ID,
+ Name: item.Name,
+ Pass: item.Pass,
+ Active: item.Active,
+ Created: item.Created,
+ Updated: item.Updated,
+ Contacts: mapping.ToContactEntitySlice(item.Contacts),
+ Profiles: mapping.mapper.Profile.ToProfileEntitySlice(item.Profiles),
+ Organizations: mapping.mapper.Organization.ToOrganizationEntitySlice(item.Organizations),
+ Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types),
+ }
+
+ if user.Name == "" {
+ user.Name = fmt.Sprintf("%s %s", item.First, item.Last)
+ }
+
+ if item.Email != nil {
+ user.Email = *item.Email
+ }
+
+ if item.PhoneNumber != nil {
+ user.PhoneNumber = *item.PhoneNumber
+ }
+
+ if item.Gender != nil {
+ user.Gender = *item.Gender
+ }
+
+ if item.Member != nil {
+ user.Member = *item.Member
+ }
+
+ if item.BirthDate != nil {
+ user.BirthDate = *item.BirthDate
+ }
+
+ return user
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *userMapping) ToUserEntitySlice(list []viewmodel.User) (retVal []entity.User) {
+ retVal = make([]entity.User, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToUserEntity(item))
+ }
+
+ return retVal
+}
+
+// ToContactTypeEntity maps a Contact type entity to Contact Type view model
+func (mapping *userMapping) ToContactTypeEntity(item viewmodel.ContactType) entity.ContactType {
+ return entity.ContactType{
+ Key: item.Key,
+ Value: item.Value,
+ }
+}
+
+// ToContactTypeEntitySlice maps a User entity slice to Contact Type view model slice
+func (mapping *userMapping) ToContactTypeEntitySlice(list []viewmodel.ContactType) (retVal []entity.ContactType) {
+ retVal = make([]entity.ContactType, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToContactTypeEntity(item))
+ }
+
+ return retVal
+}
+
+// ToContactTypeModel maps a Contact type entity to Contact Type view model
+func (mapping *userMapping) ToContactTypeModel(item entity.ContactType) viewmodel.ContactType {
+ return viewmodel.ContactType{
+ Key: item.Key,
+ Value: item.Value,
+ }
+}
+
+// ToContactTypeModelSlice maps a User entity slice to Contact Type view model slice
+func (mapping *userMapping) ToContactTypeModelSlice(list []entity.ContactType) (retVal []viewmodel.ContactType) {
+ retVal = make([]viewmodel.ContactType, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToContactTypeModel(item))
+ }
+
+ return retVal
+}
+
+// ToContactModel maps a Contact entity to Contact view model
+func (mapping *userMapping) ToContactModel(item entity.ContactInfo) viewmodel.Contact {
+ return viewmodel.Contact{
+ Type: mapping.ToContactTypeModel(item.Type),
+ Value: item.Value,
+ }
+}
+
+// ToContactModelSlice maps a Contact entity slice to Contact view model slice
+func (mapping *userMapping) ToContactModelSlice(list []entity.ContactInfo) (retVal []viewmodel.Contact) {
+ retVal = make([]viewmodel.Contact, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToContactModel(item))
+ }
+
+ return retVal
+}
+
+// ToContactEntity maps a Contact entity to Contact view model
+func (mapping *userMapping) ToContactEntity(item viewmodel.Contact) entity.ContactInfo {
+ return entity.ContactInfo{
+ Type: mapping.ToContactTypeEntity(item.Type),
+ Value: item.Value,
+ }
+}
+
+// ToContactEntitySlice maps a Contact entity slice to Contact view model slice
+func (mapping *userMapping) ToContactEntitySlice(list []viewmodel.Contact) (retVal []entity.ContactInfo) {
+ retVal = make([]entity.ContactInfo, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToContactEntity(item))
+ }
+
+ return retVal
+}
diff --git a/application/entitymapping/visit.go b/application/entitymapping/visit.go
new file mode 100644
index 0000000..daffb9b
--- /dev/null
+++ b/application/entitymapping/visit.go
@@ -0,0 +1,131 @@
+package entitymapping
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// rideMapping has method to map ride entities to view models
+type visitMapping struct {
+ mapper *Mapper
+}
+
+// ToVisitEntity maps a User entity to User view model
+func (mapping *visitMapping) ToVisitEntity(item viewmodel.Visit) entity.Visit {
+ return entity.Visit{
+ UUID: item.UUID,
+ Status: mapping.ToVisitStatusEntity(item.Status),
+ User: mapping.mapper.User.ToUserEntity(item.User),
+ VisitDuration: item.VisitDuration,
+ VisitDatetime: item.VisitDatetime,
+ PickupDatetime: item.PickupDatetime,
+ Notes: item.Notes,
+ PickupAddressID: item.PickupAddressID,
+ DestinationAddressID: item.DestinationAddressID,
+ Pickup: mapping.mapper.Ride.ToLocationEntity(item.Pickup),
+ Provider: mapping.mapper.Provider.ToProviderRespEntity(item.Provider),
+ CreatedUser: mapping.mapper.User.ToUserEntity(item.CreatedUser),
+ Created: item.CreatedDate,
+ Updated: item.UpdatedDate,
+ ReturnDate: item.ReturnDate,
+ ExternalID: item.ExternalID,
+ TripType: mapping.ToTripTypeEntity(item.TripType),
+ Rides: mapping.mapper.Ride.ToRideInternalEntitySlice(item.Rides),
+ }
+}
+
+func (mapping *visitMapping) ToVisitStatusEntity(item viewmodel.VisitStatus) entity.VisitStatus {
+ return entity.VisitStatus{
+ Value: item.Value,
+ Key: item.Key,
+ }
+}
+
+// ToVisitEntity maps a User entity to User view model
+func (mapping *visitMapping) ToVisitModel(item entity.Visit) viewmodel.Visit {
+ return viewmodel.Visit{
+ UUID: item.UUID,
+ Status: mapping.ToVisitStatusModel(item.Status),
+ User: mapping.mapper.User.ToUserModel(item.User),
+ VisitDuration: item.VisitDuration,
+ VisitDatetime: item.VisitDatetime,
+ PickupDatetime: item.PickupDatetime,
+ Notes: item.Notes,
+ PickupAddressID: item.PickupAddressID,
+ DestinationAddressID: item.DestinationAddressID,
+ Pickup: mapping.mapper.Ride.ToLocationModel(item.Pickup),
+ Provider: mapping.mapper.Provider.ToProviderRespModel(item.Provider),
+ CreatedUser: mapping.mapper.User.ToUserModel(item.CreatedUser),
+ CreatedDate: item.Created,
+ UpdatedDate: item.Updated,
+ ReturnDate: item.ReturnDate,
+ ExternalID: item.ExternalID,
+ TripType: mapping.ToTripTypeModel(item.TripType),
+ Rides: mapping.mapper.Ride.ToRideModelSlice(item.Rides),
+ }
+}
+
+func (mapping *visitMapping) ToVisitStatusModel(item entity.VisitStatus) viewmodel.VisitStatus {
+ return viewmodel.VisitStatus{
+ Value: item.Value,
+ Key: item.Key,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *visitMapping) ToVisitEntitySlice(list []viewmodel.Visit) (retVal []entity.Visit) {
+ retVal = make([]entity.Visit, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToVisitEntity(item))
+ }
+
+ return retVal
+}
+
+// ToRideModelSlice maps a Ride entity slice to Ride view model slice
+func (mapping *visitMapping) ToVisitModelSlice(list []entity.Visit) (retVal []viewmodel.Visit) {
+ retVal = make([]viewmodel.Visit, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToVisitModel(item))
+ }
+
+ return retVal
+}
+
+func (mapping *visitMapping) ToTripTypeModel(item entity.TripType) viewmodel.TripType {
+ return viewmodel.TripType{
+ Value: item.Value,
+ Key: item.Key,
+ }
+}
+
+func (mapping *visitMapping) ToTripTypeEntity(item viewmodel.TripType) entity.TripType {
+ return entity.TripType{
+ Value: item.Value,
+ Key: item.Key,
+ }
+}
+
+// ToUserEntitySlice maps a User entity slice to User view model slice
+func (mapping *visitMapping) ToTripTypeEntitySlice(list []viewmodel.TripType) (retVal []entity.TripType) {
+ retVal = make([]entity.TripType, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToTripTypeEntity(item))
+ }
+
+ return retVal
+}
+
+// ToRideModelSlice maps a Ride entity slice to Ride view model slice
+func (mapping *visitMapping) ToTripTypeModelSlice(list []entity.TripType) (retVal []viewmodel.TripType) {
+ retVal = make([]viewmodel.TripType, 0)
+
+ for _, item := range list {
+ retVal = append(retVal, mapping.ToTripTypeModel(item))
+ }
+
+ return retVal
+}
diff --git a/application/notificationservice/notificationservice.go b/application/notificationservice/notificationservice.go
new file mode 100644
index 0000000..0633e6c
--- /dev/null
+++ b/application/notificationservice/notificationservice.go
@@ -0,0 +1,31 @@
+package notificationservice
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+var (
+ instance *Service
+ once sync.Once
+)
+
+// Service holds the domain service repositories
+type Service struct {
+ Twilio *twilioService
+}
+
+// New returns a new domain Service instance
+func New(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, cache contract.CacheManager) *Service {
+ once.Do(func() {
+ instance = &Service{
+ Twilio: newTwilioService(svc, mapper, cfg, cache),
+ }
+ })
+
+ return instance
+}
diff --git a/application/notificationservice/twilio.go b/application/notificationservice/twilio.go
new file mode 100644
index 0000000..0f40dbf
--- /dev/null
+++ b/application/notificationservice/twilio.go
@@ -0,0 +1,259 @@
+package notificationservice
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain"
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+const (
+ twilioMessageURL = "https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json"
+ twilioNumbersURL = "https://api.twilio.com/2010-04-01/Accounts/%s/AvailablePhoneNumbers/US/Local.json"
+ twiliActualNumbersURL = "https://api.twilio.com/2010-04-01/Accounts/%s/IncomingPhoneNumbers.json"
+)
+
+// twilioService holds methods to twillio application service
+type twilioService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+ cfg *config.Config
+ urlMessage string
+ urlNumber string
+ urlActualNumber string
+ cache contract.CacheManager
+}
+
+// newTwilioService returns a twilioService instance
+func newTwilioService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, cache contract.CacheManager) *twilioService {
+ return &twilioService{
+ svc: svc,
+ mapEntity: mapper,
+ cfg: cfg,
+ urlMessage: fmt.Sprintf(twilioMessageURL, cfg.Twilio.Account),
+ urlNumber: fmt.Sprintf(twilioNumbersURL, cfg.Twilio.Account),
+ urlActualNumber: fmt.Sprintf(twiliActualNumbersURL, cfg.Twilio.Account),
+ cache: cache,
+ }
+}
+
+func (s twilioService) GetProxyNumber(to string) (viewmodel.ProxyNumber, error) {
+ key := "proxy" + to
+ var number viewmodel.ProxyNumber
+ err := s.cache.GetStruct(key, &number)
+ if err != nil || err == domain.ErrCacheMiss {
+ return number, err
+ } else {
+ return number, nil
+ }
+}
+
+func (s twilioService) GetAvaliableNumbers(to string) (viewmodel.ListNumbers, error) {
+ if to != "" {
+ if strings.Contains(to, "+1") {
+ to = strings.Replace(to, "+1", "", -1)
+ }
+
+ area := to[0:3]
+
+ msgData := url.Values{}
+ msgData.Set("PhoneNumber", area)
+
+ client := &http.Client{}
+ req, _ := http.NewRequest("GET", s.urlActualNumber+"?"+msgData.Encode(), bytes.NewBuffer([]byte{}))
+
+ req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
+ resp, err := client.Do(req)
+ if err != nil {
+ fmt.Println("Error Twilio: ", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode >= 200 && resp.StatusCode < 300 {
+ var data viewmodel.ListNumbers
+ decoder := json.NewDecoder(resp.Body)
+ err := decoder.Decode(&data)
+ if err != nil {
+ return viewmodel.ListNumbers{}, err
+ }
+
+ return data, nil
+ } else {
+ return viewmodel.ListNumbers{}, errors.New(resp.Status)
+ }
+ }
+ return viewmodel.ListNumbers{}, nil
+}
+
+func (s twilioService) GetAvaliableNewNumbers(to string) (viewmodel.ListNumbers, error) {
+ if to != "" {
+ if strings.Contains(to, "+1") {
+ to = strings.Replace(to, "+1", "", -1)
+ }
+
+ area := to[0:3]
+
+ msgData := url.Values{}
+ msgData.Set("AreaCode", area)
+
+ client := &http.Client{}
+ req, _ := http.NewRequest("GET", s.urlNumber+"?"+msgData.Encode(), bytes.NewBuffer([]byte{}))
+
+ req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
+ resp, err := client.Do(req)
+ if err != nil {
+ fmt.Println("Error Twilio: ", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode >= 200 && resp.StatusCode < 300 {
+ var data viewmodel.ListNumbers
+ decoder := json.NewDecoder(resp.Body)
+ err := decoder.Decode(&data)
+ if err != nil {
+ return viewmodel.ListNumbers{}, err
+ }
+
+ return data, nil
+ } else {
+ return viewmodel.ListNumbers{}, errors.New(resp.Status)
+ }
+ }
+ return viewmodel.ListNumbers{}, nil
+}
+
+func (s twilioService) SaveNewNumber(number viewmodel.Number) (viewmodel.Number, error) {
+ phoneNumber := number.PhoneNumber
+ if strings.Contains(phoneNumber, "+1") {
+ phoneNumber = strings.Replace(phoneNumber, "+1", "", -1)
+ }
+ area := phoneNumber[0:3]
+
+ msgData := url.Values{}
+ msgData.Set("PhoneNumber", number.PhoneNumber)
+ msgData.Set("AreaCode", area)
+ msgData.Set("FriendlyName", number.FriendlyName)
+ msgData.Set("SmsApplicationSid", s.cfg.Twilio.TwiMLSID)
+ msgDataReader := *strings.NewReader(msgData.Encode())
+
+ client := &http.Client{}
+ req, _ := http.NewRequest("POST", s.urlActualNumber, &msgDataReader)
+ req.Header.Add("Accept", "application/json")
+ req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
+ resp, err := client.Do(req)
+ if err != nil {
+ fmt.Println("Error Twilio: ", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode >= 200 && resp.StatusCode < 300 {
+ decoder := json.NewDecoder(resp.Body)
+ err := decoder.Decode(&number)
+ if err != nil {
+ return viewmodel.Number{}, err
+ }
+
+ return number, nil
+ } else {
+ return viewmodel.Number{}, errors.New(resp.Status)
+ }
+}
+
+func (s twilioService) GetValidNumber(from string, to string) (viewmodel.Number, error) {
+ list, err := s.GetAvaliableNumbers(to)
+ if err != nil {
+ return viewmodel.Number{}, err
+ }
+
+ if len(list.IncomingPhones) > 0 {
+ return list.IncomingPhones[0], nil
+ }
+
+ list, err = s.GetAvaliableNewNumbers(to)
+ if err != nil {
+ return viewmodel.Number{}, err
+ }
+
+ if len(list.AvailableNumbers) > 0 {
+ number, err := s.SaveNewNumber(list.AvailableNumbers[0])
+ if err != nil {
+ fmt.Println("Error on GetValidNumber: ", err.Error())
+ return viewmodel.Number{}, err
+ }
+
+ return number, nil
+ } else {
+ return viewmodel.Number{}, errors.New("No new number available")
+ }
+}
+
+func (s twilioService) GetNumber(from string, to string) (string, error) {
+ number, err := s.GetValidNumber(from, to)
+ if err != nil {
+ return from, err
+ }
+
+ return number.PhoneNumber, nil
+}
+
+func (s twilioService) SendSMS(from string, to string, message string) error {
+ if from == "" {
+ return errors.New("TwilioService.SendSMS: from parameter is mandatory")
+ }
+ if to == "" {
+ return errors.New("TwilioService.SendSMS: to parameter is mandatory")
+ }
+ if message == "" {
+ return errors.New("TwilioService.SendSMS: message parameter is mandatory")
+ }
+
+ senderNumber, err := s.GetNumber(from, to)
+ if err != nil {
+ return err
+ }
+
+ msgData := url.Values{}
+ msgData.Set("To", to)
+ msgData.Set("From", senderNumber)
+ msgData.Set("Body", message)
+
+ msgDataReader := *strings.NewReader(msgData.Encode())
+
+ client := &http.Client{}
+ req, _ := http.NewRequest("POST", s.urlMessage, &msgDataReader)
+
+ req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
+ req.Header.Add("Accept", "application/json")
+ req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+
+ resp, err := client.Do(req)
+ if err != nil {
+ fmt.Println("Error Twilio: ", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode >= 200 && resp.StatusCode < 300 {
+ var data map[string]interface{}
+ decoder := json.NewDecoder(resp.Body)
+ err := decoder.Decode(&data)
+ if err != nil {
+ return err
+ }
+ } else {
+ fmt.Println("Error on Twilio Response: ", resp.Status)
+ return errors.New(resp.Status)
+ }
+
+ return nil
+}
diff --git a/application/third/eligibility/bcbsi/bcbsi.go b/application/third/eligibility/bcbsi/bcbsi.go
new file mode 100644
index 0000000..a9d2da7
--- /dev/null
+++ b/application/third/eligibility/bcbsi/bcbsi.go
@@ -0,0 +1,28 @@
+package bcbsi
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+var (
+ instance *Service
+ once sync.Once
+)
+
+// Service holds the domain service repositories
+type Service struct {
+ BXE *bxeService
+}
+
+// New returns a new domain Service instance
+func New(cfg *config.Config) *Service {
+ once.Do(func() {
+ instance = &Service{
+ BXE: newBXEService(cfg),
+ }
+ })
+
+ return instance
+}
diff --git a/application/third/eligibility/bcbsi/bcbsimodel/eligibility.go b/application/third/eligibility/bcbsi/bcbsimodel/eligibility.go
new file mode 100644
index 0000000..502a16b
--- /dev/null
+++ b/application/third/eligibility/bcbsi/bcbsimodel/eligibility.go
@@ -0,0 +1,150 @@
+package bcbsimodel
+
+import (
+ "encoding/xml"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+)
+
+func GetEnvelope(eligibility viewmodel.Eligibility) Envelope {
+ soapEnvelope := Envelope{}
+ soapEnvelope.Namespace = "http://schemas.xmlsoap.org/soap/envelope/"
+ soapEnvelope.Body.MemberEligibilityRequest = GetEligibilityRequest(eligibility)
+ soapEnvelope.Body.MemberEligibilityRequest.Namespace = "http://v30.bx.services.bcbsa.com/eligibility-ext"
+ return soapEnvelope
+}
+
+func GetEligibilityRequest(eligibility viewmodel.Eligibility) MemberEligibilityRequest {
+ retVal := MemberEligibilityRequest{}
+ retVal.Version.MajorVersion = 3
+ retVal.Version.MinorVersion = 0
+
+ retVal.QueryHeader.TimeSent = time.Now().Format("2006-01-02T15:04:05")
+ retVal.QueryHeader.TrackingID = eligibility.TrackingID
+ retVal.Query.PayerInfo.PayerID = eligibility.Payer.PayerID
+ retVal.Query.PayerInfo.PayerName = eligibility.Payer.PayerName
+
+ retVal.Query.ProviderInfo.ProviderID = eligibility.Provider.ProviderID
+ retVal.Query.ProviderInfo.ProviderNPI = eligibility.Provider.ProviderNPI
+ retVal.Query.ProviderInfo.Provider.Organization = eligibility.Provider.ProviderName
+ retVal.Query.ProviderInfo.Provider.Name.First = eligibility.Provider.Name.First
+ retVal.Query.ProviderInfo.Provider.Name.Last = eligibility.Provider.Name.Last
+ retVal.Query.ProviderInfo.Provider.Name.Middle = eligibility.Provider.Name.Middle
+ retVal.Query.SubscriberInfo.SubscriberID = eligibility.Subscriber.SubscriberID
+ retVal.Query.SubscriberInfo.PatientType = eligibility.Subscriber.PatientType
+ retVal.Query.SubscriberInfo.Name.First = eligibility.Subscriber.Name.First
+ retVal.Query.SubscriberInfo.Name.Last = eligibility.Subscriber.Name.Last
+ retVal.Query.SubscriberInfo.Name.Middle = eligibility.Subscriber.Name.Middle
+ retVal.Query.SubscriberInfo.DemographicInfo.DateOfBirth = eligibility.Subscriber.DemographicInfo.DateOfBirth.Format("20060102")
+ retVal.Query.SubscriberInfo.DemographicInfo.GenderCode = eligibility.Subscriber.DemographicInfo.Gender
+
+ var dependents []Dependent
+ for _, d := range eligibility.Subscriber.Dependents {
+ dependent := Dependent{}
+ dependent.PatientAccountNumber = d.PatientAccountNumber
+ dependent.DemographicInfo.DateOfBirth = d.DemographicInfo.DateOfBirth.Format("20060102")
+ dependent.DemographicInfo.GenderCode = d.DemographicInfo.Gender
+ dependent.Name.First = d.Name.First
+ dependent.Name.Last = d.Name.Last
+ dependent.Name.Middle = d.Name.Middle
+ dependents = append(dependents, dependent)
+ }
+ if len(dependents) == 0 {
+ dependents = append(dependents, Dependent{})
+ }
+
+ retVal.Query.SubscriberInfo.DependentInfo.Dependents = dependents
+ retVal.Query.ServiceInfo.DateOfService = eligibility.ServiceInfo.DateOfService.Format("20060102")
+ retVal.Query.ServiceInfo.ServiceTypeCodes.ServiceTypeCode = eligibility.ServiceInfo.ServiceTypeCodes
+
+ return retVal
+}
+
+type Envelope struct {
+ XMLName xml.Name `xml:"soap:Envelope"`
+ Body EnvelopeBody `xml:"soap:Body"`
+ Namespace string `xml:"xmlns:soap,attr"`
+}
+
+type EnvelopeBody struct {
+ MemberEligibilityRequest MemberEligibilityRequest `xml:"elig:MemberEligibilityRequest"`
+}
+
+type MemberEligibilityRequest struct {
+ Version Version `xml:"version"`
+ QueryHeader QueryHeader `xml:"elig:eligibility-benefits-query-header"`
+ Query Query `xml:"elig:eligibility-benefits-query"`
+ Namespace string `xml:"xmlns:elig,attr"`
+}
+
+type Version struct {
+ MajorVersion int64 `xml:"majorVersion"`
+ MinorVersion int64 `xml:"minorVersion"`
+}
+
+type QueryHeader struct {
+ TrackingID string `xml:"tracking-id"`
+ TimeSent string `xml:"time-sent"`
+}
+
+type Query struct {
+ PayerInfo PayerInfo `xml:"elig:payer-info"`
+ ProviderInfo ProviderInfo `xml:"elig:provider-info"`
+ SubscriberInfo SubscriberInfo `xml:"elig:subscriber-info"`
+ ServiceInfo ServiceInfo `xml:"elig:service-info"`
+}
+
+type ServiceInfo struct {
+ DateOfService string `xml:"elig:date-of-service"`
+ ServiceTypeCodes ServiceTypeCodes `xml:"elig:service-type-codes"`
+}
+
+type ServiceTypeCodes struct {
+ ServiceTypeCode []string `xml:"elig:service-type-code"`
+}
+
+type SubscriberInfo struct {
+ PatientType string `xml:"elig:patient-type"`
+ SubscriberID string `xml:"elig:subscriber-id"`
+ Name Name `xml:"elig:name"`
+ DemographicInfo DemographicInfo `xml:"elig:demographic-info"`
+ DependentInfo DependentInfo `xml:"elig:dependent-info"`
+}
+
+type DependentInfo struct {
+ Dependents []Dependent `xml:"elig:dependent"`
+}
+
+type Dependent struct {
+ PatientAccountNumber string `xml:"elig:patient-account-number"`
+ Name Name `xml:"elig:name"`
+ DemographicInfo DemographicInfo `xml:"elig:demographic-info"`
+}
+
+type DemographicInfo struct {
+ DateOfBirth string `xml:"elig:date-of-birth"`
+ GenderCode string `xml:"elig:gender-code"`
+}
+
+type ProviderInfo struct {
+ ProviderID string `xml:"elig:provider-id"`
+ ProviderNPI string `xml:"elig:provider-npi"`
+ Provider Provider `xml:"elig:provider-name"`
+}
+
+type Provider struct {
+ Organization string `xml:"organization"`
+ Name Name `xml:"elig:name"`
+}
+
+type Name struct {
+ First string `xml:"elig:first"`
+ Last string `xml:"elig:last"`
+ Middle string `xml:"elig:middle"`
+}
+
+type PayerInfo struct {
+ PayerName string `xml:"elig:payer-name"`
+ PayerID string `xml:"elig:payer-id"`
+}
diff --git a/application/third/eligibility/bcbsi/bcbsimodel/response.go b/application/third/eligibility/bcbsi/bcbsimodel/response.go
new file mode 100644
index 0000000..88f0afd
--- /dev/null
+++ b/application/third/eligibility/bcbsi/bcbsimodel/response.go
@@ -0,0 +1,44 @@
+package bcbsimodel
+
+import (
+ "encoding/xml"
+)
+
+type EnvelopeResponse struct {
+ XMLName xml.Name `xml:"Envelope"`
+ Body EnvelopeBodyResponse `xml:"Body"`
+}
+
+type EnvelopeBodyResponse struct {
+ MemberEligibilityResponse MemberEligibilityResponse `xml:"MemberEligibilityResponse"`
+}
+
+type MemberEligibilityResponse struct {
+ Version Version `xml:"version" json:"-"`
+ QueryResult QueryResult `xml:"eligibility-benefits-query-results" json:"results"`
+}
+
+type QueryResult struct {
+ HIPPA271 HIPAA271 `xml:"vcml-271" json:"raw"`
+ QueryResultSummary QueryResultSummary `xml:"query-result-summary" json:"summary"`
+}
+
+type HIPAA271 struct {
+ T271 string `xml:"t271" json:"t271"`
+}
+
+type QueryResultSummary struct {
+ BenefitsFound bool `xml:"benefits-found" json:"benefits_found"`
+ ProcessingInfo ProcessingInfo `xml:"processing-info" json:"-"`
+}
+
+type ProcessingInfo struct {
+ Message string `xml:"message" json:"-"`
+}
+
+type EntityResponse struct {
+ EntityID int64 `json:"entity_id"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Status bool `json:"status"`
+}
diff --git a/application/third/eligibility/bcbsi/bxe.go b/application/third/eligibility/bcbsi/bxe.go
new file mode 100644
index 0000000..26daff3
--- /dev/null
+++ b/application/third/eligibility/bcbsi/bxe.go
@@ -0,0 +1,126 @@
+package bcbsi
+
+import (
+ "bytes"
+ "crypto/md5"
+ "encoding/hex"
+ "encoding/xml"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/pquerna/ffjson/ffjson"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi/bcbsimodel"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+type bxeService struct {
+ cfg *config.Config
+}
+
+func newBXEService(cfg *config.Config) *bxeService {
+ return &bxeService{
+ cfg: cfg,
+ }
+}
+
+func (s bxeService) getSignature(APIKey string, secretKey string) string {
+ rawKey := fmt.Sprintf("%s%s%v", APIKey, secretKey, time.Now().Unix())
+
+ hasher := md5.New()
+ hasher.Write([]byte(rawKey))
+ key := hex.EncodeToString(hasher.Sum(nil))
+
+ return strings.ToLower(key)
+}
+
+func (s bxeService) GetPayerDetails(subscriberID string) ([]bcbsimodel.EntityResponse, error) {
+ apiKey := s.cfg.Blue365.APIKey
+ secretKey := s.cfg.Blue365.Secret
+ URL := s.cfg.Blue365.URL
+ prefix := subscriberID[:3]
+
+ client := &http.Client{}
+ req, _ := http.NewRequest("GET", URL+"/"+prefix, bytes.NewBuffer([]byte{}))
+ req.Header.Add("X-Api-Key", apiKey)
+ req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
+
+ resp, err := client.Do(req)
+ if err != nil {
+ fmt.Println("Error Blue365: ", err)
+ return nil, err
+ }
+ defer resp.Body.Close()
+ bReturn, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ fmt.Println("Error Blue365: ", err)
+ return nil, err
+ }
+
+ var response []bcbsimodel.EntityResponse
+ err = ffjson.Unmarshal(bReturn, &response)
+ if err != nil {
+ fmt.Println("Error Blue365: ", err)
+ return nil, err
+ }
+
+ return response, nil
+}
+
+func (s bxeService) CheckEligibility(eligibility viewmodel.Eligibility) (bcbsimodel.MemberEligibilityResponse, error) {
+ payer, err := s.GetPayerDetails(eligibility.Subscriber.SubscriberID)
+ if err != nil {
+ return bcbsimodel.MemberEligibilityResponse{}, err
+ }
+
+ eligibility.Payer.PayerID = payer[0].ID
+ eligibility.Payer.PayerName = payer[0].Name
+
+ envelope := bcbsimodel.GetEnvelope(eligibility)
+ apiKey := s.cfg.BXE.APIKey
+ secretKey := s.cfg.BXE.Secret
+
+ bObj, err := xml.Marshal(envelope)
+ if err != nil {
+ return bcbsimodel.MemberEligibilityResponse{}, err
+ }
+
+ client := &http.Client{}
+ req, _ := http.NewRequest("POST", s.cfg.BXE.URL, bytes.NewBuffer(bObj))
+ req.Header.Add("Soapaction", "CheckEligibility")
+ req.Header.Add("Content-Type", "text/xml")
+ req.Header.Add("X-Api-Key", apiKey)
+ req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
+
+ resp, err := client.Do(req)
+ if err != nil {
+ fmt.Println("Error WebService: ", err)
+ return bcbsimodel.MemberEligibilityResponse{}, err
+ }
+ defer resp.Body.Close()
+
+ bReturn, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ fmt.Println("Error WebService: ", err)
+ return bcbsimodel.MemberEligibilityResponse{}, err
+ }
+
+ sResponse := string(bReturn)
+ sResponse = strings.Replace(sResponse, "soapenv:Envelope", "Envelope", -1)
+ sResponse = strings.Replace(sResponse, "soapenv:Body", "Body", -1)
+ sResponse = strings.Replace(sResponse, "ns2:", "", -1)
+
+ var result bcbsimodel.EnvelopeResponse
+ err = xml.Unmarshal([]byte(sResponse), &result)
+ if err != nil {
+ fmt.Println("Error WebService: ", err)
+ return bcbsimodel.MemberEligibilityResponse{}, err
+ }
+
+ return result.Body.MemberEligibilityResponse, nil
+}
diff --git a/application/third/npd/npd.go b/application/third/npd/npd.go
new file mode 100644
index 0000000..b976d81
--- /dev/null
+++ b/application/third/npd/npd.go
@@ -0,0 +1,28 @@
+package npd
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+var (
+ instance *Service
+ once sync.Once
+)
+
+// Service holds the domain service repositories
+type Service struct {
+ Provider *providerService
+}
+
+// New returns a new domain Service instance
+func New(cfg *config.Config) *Service {
+ once.Do(func() {
+ instance = &Service{
+ Provider: newProviderService(cfg),
+ }
+ })
+
+ return instance
+}
diff --git a/application/third/npd/npdmodel/provider.go b/application/third/npd/npdmodel/provider.go
new file mode 100644
index 0000000..3c6cefc
--- /dev/null
+++ b/application/third/npd/npdmodel/provider.go
@@ -0,0 +1,124 @@
+package npdmodel
+
+type ProviderHeaderResponse struct {
+ ResultStatus string `json:"resultStatus"`
+ Count CountResponse `json:"counts"`
+ Providers []ProviderResponse `json:"providers"`
+ FacetFields []FacetField `json:"facetEntries"`
+}
+
+type CountResponse struct {
+ Total string `json:"total"`
+ Groups string `json:"groups"`
+}
+
+type FacetField struct {
+ Name string `json:"name"`
+ FacetEntries []map[string]string `json:"facetEntries"`
+}
+
+type ProviderResponse struct {
+ MukID string `json:"mukId"`
+ FivePartKeyGroups []PartKeyGroup `json:"fivePartKeyGroups"`
+ OrgName string `json:"orgName"`
+ Gender string `json:"gender"`
+ AcceptNewPatients string `json:"acceptNewPatients"`
+ ProviderName string `json:"providerName"`
+ FirstName string `json:"firstName"`
+ LastName string `json:"lastName"`
+ MiddleName string `json:"middleName"`
+ ProviderTitle string `json:"providerTitle"`
+ StreetName1 string `json:"streetName_1"`
+ StreetName2 string `json:"streetName_2"`
+ CityName string `json:"cityName"`
+ State string `json:"state"`
+ ZipCode string `json:"zipCode"`
+ Country string `json:"country"`
+ Latitude string `json:"latitude"`
+ Longitude string `json:"longitude"`
+ PhoneNumber string `json:"phoneNumber"`
+ ProviderEntityName string `json:"providerEntityName"`
+ ProviderEntityCode string `json:"providerEntityCode"`
+ ProviderTypeCode []ProviderTypeCode `json:"providerTypeCode"`
+ Distance string `json:"distance"`
+ AvailabilityOfCost string `json:"availabilityOfCost"`
+ TDDPhoneNumber string `json:"tddPhoneNumber"`
+ ExtendedOfficeHours string `json:"extendedOfficeHours"`
+ ProviderCountyCode string `json:"providerCountyCode"`
+ ProviderCountyName string `json:"providerCountyName"`
+ HospitalAffiliationNames []HospitalAffiliationNames `json:"hospitalAffiliationNames"`
+ ProviderAffiliationNumber string `json:"providerAffiliationNumber"`
+ ProviderAffiliationName string `json:"providerAffiliationName"`
+ LanguagesSpoken []Languages `json:"languagesSpoken"`
+ OfficeLanguagesSpoken []Languages `json:"officeLanguagesSpoken"`
+ MedSchool string `json:"medSchool"`
+ MedSchoolYear string `json:"medSchoolYear"`
+ Internship string `json:"internship"`
+ Residence string `json:"residency"`
+ Specialty1 string `json:"specialty1"`
+ Specialty2 string `json:"specialty2"`
+ Specialty3 string `json:"specialty3"`
+ Specialty4 string `json:"specialty4"`
+ Certification1 string `json:"certification1"`
+ Certification2 string `json:"certification2"`
+ Certification3 string `json:"certification3"`
+ Certification4 string `json:"certification4"`
+}
+
+type HospitalAffiliationNames struct {
+ HospAffProvOrgName string `json:"hospAffProvOrgName"`
+}
+
+type Languages struct {
+ Code string `json:"code"`
+}
+
+type ProviderTypeCode struct {
+ Code string `json:"code"`
+}
+
+type PartKeyGroup struct {
+ ProviderNum string `json:"providerNum"`
+ ProviderNumSuffix string `json:"providerNumSuffix"`
+ LocationSeqNum string `json:"locationSeqNum"`
+ PlanCode string `json:"planCode"`
+ ProductID string `json:"productId"`
+ TreatmentCategoryCode string `json:"treatmentCategoryCode"`
+}
+
+// ProviderSearchParams entity data
+type ProviderSearchParams struct {
+ Name string
+ AlphaPrefix string
+ SearchBy string
+ Specialty string
+ Languages string
+ OfficeLanguages string
+ Gender string
+ AcceptNewPatients string
+ TreatmentCategoryCode string
+ SummaryScore string
+ AvailabilityOfCost string
+ AvailabilityOfQuality string
+ ExtendedOfficeHours string
+ HospitalAffiliation string
+ ProviderAffiliation string
+ ProviderEntityName string
+ NameRange string
+ BluPhyRcgIndicator string
+ Latitude float64
+ Longitude float64
+ Distance int64
+ Offset int64
+ Limit int64
+ SortBy string
+ FacetAcceptNewPatients string
+ FacetGender string
+ FacetExtendedOfficeHours string
+ FacetProviderEntityName string
+ FacetSummaryScore string
+ FacetLanguage string
+ FacetOfficeLanguages string
+ FacetHospitalAffiliations string
+ FacetProviderAffiliations string
+}
diff --git a/application/third/npd/provider.go b/application/third/npd/provider.go
new file mode 100644
index 0000000..b74bb2b
--- /dev/null
+++ b/application/third/npd/provider.go
@@ -0,0 +1,56 @@
+package npd
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+
+ "github.com/pquerna/ffjson/ffjson"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+type providerService struct {
+ cfg *config.Config
+}
+
+func newProviderService(cfg *config.Config) *providerService {
+ return &providerService{
+ cfg: cfg,
+ }
+}
+
+func (c *providerService) GetProviders(searchParams npdmodel.ProviderSearchParams) (npdmodel.ProviderHeaderResponse, error) {
+ providerURL := "https://api-pve.bcbs.com/Providers/V30%s"
+ params := "?name=%s&alphaPrefix=BCB&lat=%v&long=%v&distance=%v&offset=%v&limit=%v&sortBy=%s&facetAcceptNewPatients=%s&facetGender=%s&facetExtendedOfficeHours=%s&facetProviderEntityName=%s&facetSummaryScore=%s&facetlanguage=%s&facetOfficelanguages=%s&facetHospitalAffiliations=%s&facetProviderAffiliations=%s"
+ params = fmt.Sprintf(params, url.QueryEscape(searchParams.Name), searchParams.Latitude, searchParams.Longitude, searchParams.Distance, searchParams.Offset, searchParams.Limit, url.QueryEscape(searchParams.SortBy), url.QueryEscape(searchParams.FacetAcceptNewPatients), url.QueryEscape(searchParams.FacetGender), url.QueryEscape(searchParams.FacetExtendedOfficeHours), url.QueryEscape(searchParams.FacetProviderEntityName), url.QueryEscape(searchParams.FacetSummaryScore), url.QueryEscape(searchParams.FacetLanguage), url.QueryEscape(searchParams.FacetOfficeLanguages), url.QueryEscape(searchParams.FacetHospitalAffiliations), url.QueryEscape(searchParams.FacetProviderAffiliations))
+
+ providerURL = fmt.Sprintf(providerURL, params)
+
+ req, err := http.NewRequest("GET", providerURL, nil)
+ if err != nil {
+ return npdmodel.ProviderHeaderResponse{}, err
+ }
+
+ req.Header.Add("X-Api-Key", "sv6fs4dyh8macvuyyzgqs45w")
+
+ client := &http.Client{}
+ resp, err := client.Do(req)
+ if err != nil {
+ return npdmodel.ProviderHeaderResponse{}, err
+ }
+ defer resp.Body.Close()
+
+ bObject, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return npdmodel.ProviderHeaderResponse{}, err
+ }
+
+ var providers npdmodel.ProviderHeaderResponse
+ if err := ffjson.Unmarshal(bObject, &providers); err != nil {
+ return npdmodel.ProviderHeaderResponse{}, err
+ }
+ return providers, nil
+}
diff --git a/application/tncservice/lyft.go b/application/tncservice/lyft.go
new file mode 100644
index 0000000..f49f5e6
--- /dev/null
+++ b/application/tncservice/lyft.go
@@ -0,0 +1,305 @@
+package tncservice
+
+import (
+ "bytes"
+ "context"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/lyft/lyft-go-sdk/lyft"
+ "github.com/pquerna/ffjson/ffjson"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/clientcredentials"
+)
+
+const (
+ lyftURL = "https://api.lyft.com/v1/"
+)
+
+// lyftService holds methods to lyft application service
+type lyftService struct {
+ svc *service.Service
+ mapEntity *entitymapping.Mapper
+ client *lyft.APIClient
+ httpClient *http.Client
+ cfg *config.Config
+ notification *notificationservice.Service
+ lyftConfig clientcredentials.Config
+ refreshToken string
+}
+
+// newLyftProdService returns a lyftService instance with production info
+func newLyftProdService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *lyftService {
+ config := clientcredentials.Config{
+ ClientID: cfg.LyftProd.Lyft.Client,
+ ClientSecret: cfg.LyftProd.Lyft.Secret,
+ TokenURL: "https://api.lyft.com/oauth/token",
+ Scopes: []string{"public", "privileged.rides.dispatch", "rides.read", "rides.request", "profile", "offline"},
+ }
+ httpClient := config.Client(context.Background())
+
+ return &lyftService{
+ svc: svc,
+ mapEntity: mapper,
+ client: lyft.NewAPIClient(httpClient, "nemt"),
+ httpClient: httpClient,
+ cfg: cfg,
+ notification: notificationService,
+ lyftConfig: config,
+ refreshToken: cfg.LyftProd.Lyft.RefreshToken,
+ }
+}
+
+// newLyftService returns a lyftService instance
+func newLyftService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *lyftService {
+ config := clientcredentials.Config{
+ ClientID: cfg.Lyft.Client,
+ ClientSecret: cfg.Lyft.Secret,
+ TokenURL: "https://api.lyft.com/oauth/token",
+ Scopes: []string{"public", "privileged.rides.dispatch", "rides.read", "rides.request", "profile", "offline"},
+ }
+ httpClient := config.Client(context.Background())
+
+ return &lyftService{
+ svc: svc,
+ mapEntity: mapper,
+ client: lyft.NewAPIClient(httpClient, "nemt"),
+ httpClient: httpClient,
+ cfg: cfg,
+ notification: notificationService,
+ lyftConfig: config,
+ refreshToken: cfg.Lyft.RefreshToken,
+ }
+}
+
+func (s *lyftService) getToken() string {
+ token, err := s.lyftConfig.Token(context.Background())
+ if err != nil {
+ fmt.Println("Error to get token: ", err)
+ return ""
+ }
+
+ return "Bearer " + token.AccessToken
+}
+
+func (s *lyftService) setTokenHeader(req *http.Request) string {
+ type Token struct {
+ GrantType string `json:"grant_type"`
+ RefreshToken string `json:"refresh_token"`
+ }
+
+ token := Token{
+ GrantType: "refresh_token",
+ RefreshToken: s.refreshToken,
+ }
+
+ bObject, err := ffjson.Marshal(token)
+ if err != nil {
+ return ""
+ }
+
+ tokenReq, err := http.NewRequest("POST", s.lyftConfig.TokenURL, bytes.NewBuffer(bObject))
+ if err != nil {
+ return ""
+ }
+ tokenReq.Header.Set("Content-Type", "application/json")
+ tokenReq.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", s.lyftConfig.ClientID, s.lyftConfig.ClientSecret))))
+ tokenReq.Header.Add("cache-control", "no-cache")
+
+ resp, err := http.DefaultClient.Do(tokenReq)
+ if err != nil {
+ fmt.Println("Error to refresh token: ", err.Error())
+ return ""
+ }
+ defer resp.Body.Close()
+
+ body, _ := ioutil.ReadAll(resp.Body)
+
+ var returnToken oauth2.Token
+ err = ffjson.Unmarshal(body, &returnToken)
+ if err != nil {
+ fmt.Println("Error to parse token: ", err.Error())
+ return ""
+ }
+
+ returnToken.SetAuthHeader(req)
+
+ return "Bearer " + returnToken.AccessToken
+}
+
+func (s *lyftService) GetRideDetails(rideRequest viewmodel.RideRequest) (viewmodel.RideRequest, error) {
+ url := lyftURL + "dispatches/" + rideRequest.RideID
+
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+ s.setTokenHeader(req)
+ req.Header.Add("Content-Type", "application/json")
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+ defer resp.Body.Close()
+
+ body, _ := ioutil.ReadAll(resp.Body)
+ var raw viewmodel.RideRequest
+ err = ffjson.Unmarshal(body, &raw)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+
+ return raw, nil
+}
+
+func (s *lyftService) GetRideStatus(rideRequest viewmodel.RideRequest, param string) (viewmodel.RideRequest, error) {
+ params := make(map[string]string)
+ params["status"] = param
+
+ bObject, err := ffjson.Marshal(params)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+
+ fmt.Println("STATUS CHANGE REQUEST ON LYFT")
+ fmt.Println("Ride ID: ", rideRequest.RideID)
+ fmt.Println("Status: ", param)
+ url := lyftURL + "sandbox/dispatches/" + rideRequest.RideID
+ req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(bObject))
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+ req.Header.Add("Content-Type", "application/json")
+
+ resp, err := s.httpClient.Do(req)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+ defer resp.Body.Close()
+
+ body, _ := ioutil.ReadAll(resp.Body)
+ fmt.Println("STATUS CHANGE RESPONSE ON LYFT")
+ fmt.Println(string(body))
+
+ var raw viewmodel.RideRequest
+ err = ffjson.Unmarshal(body, &raw)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+
+ rideRequest.Status = raw.Status
+ return s.GetRideDetails(rideRequest)
+}
+
+func (s *lyftService) CancelRide(rideRequest viewmodel.RideRequest) error {
+ finalURL := lyftURL + "dispatches/" + rideRequest.RideID + "/cancel"
+ req, err := http.NewRequest("POST", finalURL, bytes.NewBuffer([]byte{}))
+ if err != nil {
+ return err
+ }
+ s.setTokenHeader(req)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ body, _ := ioutil.ReadAll(resp.Body)
+
+ if resp.StatusCode == 204 || resp.StatusCode == 404 {
+ if err != nil {
+ fmt.Println("Error: ", err)
+ }
+
+ return nil
+ } else {
+ fmt.Println("Response Body: ", string(body))
+
+ raw := map[string]interface{}{}
+ err = ffjson.Unmarshal(body, &raw)
+ if err != nil {
+ return err
+ } else {
+ return errors.New(raw["error_description"].(string))
+ }
+ }
+}
+
+func (s *lyftService) RequestRide(rideRequest viewmodel.RideRequest) (viewmodel.RideRequest, error) {
+ bObject, err := ffjson.Marshal(rideRequest)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+
+ req, err := http.NewRequest("POST", lyftURL+"dispatches", bytes.NewBuffer(bObject))
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+ s.setTokenHeader(req)
+ req.Header.Add("Content-Type", "application/json")
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+ defer resp.Body.Close()
+ body, _ := ioutil.ReadAll(resp.Body)
+
+ var raw viewmodel.RideRequest
+ err = ffjson.Unmarshal(body, &raw)
+ if err != nil {
+ return viewmodel.RideRequest{}, err
+ }
+
+ if raw.Error != "" {
+ fmt.Println("Error to call Lyft: ", raw.Error+" - "+raw.ErrorDescription)
+ return viewmodel.RideRequest{}, errors.New("Lyft Error: " + raw.Error + " - " + raw.ErrorDescription)
+ }
+
+ return s.GetRideDetails(raw)
+}
+
+func (s *lyftService) GetETA(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
+ resp, _, err := s.client.PublicApi.GetETA(lag, log, params)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp, nil
+}
+
+func (s *lyftService) GetCost(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
+ resp, _, err := s.client.PublicApi.GetCost(lag, log, params)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp, nil
+}
+
+func (s *lyftService) GetDrivers(lag float64, log float64) (interface{}, error) {
+ resp, _, err := s.client.PublicApi.GetDrivers(lag, log)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp, nil
+}
+
+func (s *lyftService) GetTypes(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
+ resp, _, err := s.client.PublicApi.GetRideTypes(lag, log, params)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp, nil
+}
diff --git a/application/tncservice/tncservice.go b/application/tncservice/tncservice.go
new file mode 100644
index 0000000..cd5e7c8
--- /dev/null
+++ b/application/tncservice/tncservice.go
@@ -0,0 +1,33 @@
+package tncservice
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+var (
+ instance *Service
+ once sync.Once
+)
+
+// Service holds the domain service repositories
+type Service struct {
+ Lyft *lyftService
+ LyftProd *lyftService
+}
+
+// New returns a new domain Service instance
+func New(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *Service {
+ once.Do(func() {
+ instance = &Service{
+ Lyft: newLyftService(svc, mapper, cfg, notificationService),
+ LyftProd: newLyftProdService(svc, mapper, cfg, notificationService),
+ }
+ })
+
+ return instance
+}
diff --git a/application/viewmodel/address.go b/application/viewmodel/address.go
new file mode 100644
index 0000000..d499624
--- /dev/null
+++ b/application/viewmodel/address.go
@@ -0,0 +1,15 @@
+package viewmodel
+
+type Address struct {
+ UUID string `json:"address_uuid,omitempty"`
+ InternalID string `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Address string `json:"address,omitempty"`
+ AddressType string `json:"address_type,omitempty"`
+ AddressTypeName string `json:"address_type_name,omitempty"`
+ Latitude float64 `json:"lat,omitempty"`
+ Longitude float64 `json:"lng,omitempty"`
+ Type string `json:"type,omitempty"`
+ User User `json:"user,omitempty"`
+ CreatedUserUUID string `json:"-"`
+}
diff --git a/application/viewmodel/auth.go b/application/viewmodel/auth.go
new file mode 100644
index 0000000..15387e8
--- /dev/null
+++ b/application/viewmodel/auth.go
@@ -0,0 +1,9 @@
+package viewmodel
+
+// AuthResponse has data from authentication routes
+type AuthResponse struct {
+ Token string `json:"token"`
+ ValidTime int64 `json:"valid_time"`
+ ServerTime int64 `json:"server_time"`
+ User User `json:"user"`
+}
diff --git a/application/viewmodel/bxe.go b/application/viewmodel/bxe.go
new file mode 100644
index 0000000..ff1e4de
--- /dev/null
+++ b/application/viewmodel/bxe.go
@@ -0,0 +1,55 @@
+package viewmodel
+
+import (
+ "time"
+)
+
+type Eligibility struct {
+ TrackingID string `json:"tracking_id,omitempty"`
+ Payer Payer `json:"payer,omitempty"`
+ Provider Provider `json:"provider,omitempty"`
+ Subscriber Subscriber `json:"subscriber,omitempty"`
+ ServiceInfo ServiceInfo `json:"service_info,omitempty"`
+}
+
+type Payer struct {
+ PayerID string `json:"payer_id,omitempty"`
+ PayerName string `json:"payer_name,omitempty"`
+}
+
+type Provider struct {
+ ProviderID string `json:"provider_id,omitempty"`
+ ProviderNPI string `json:"provider_npi,omitempty"`
+ ProviderName string `json:"provider_name,omitempty"`
+ Name Name `json:"name,omitempty"`
+}
+
+type Name struct {
+ First string `json:"first,omitempty"`
+ Last string `json:"last,omitempty"`
+ Middle string `json:"middle,omitempty"`
+}
+
+type Subscriber struct {
+ PatientType string `json:"patient_type,omitempty"`
+ SubscriberID string `json:"subscriber_id,omitempty"`
+ Name Name `json:"name,omitempty"`
+ DemographicInfo DemographicInfo `json:"demographic_info,omitempty"`
+ Dependents []Dependent `json:"dependents,omitempty"`
+}
+
+type DemographicInfo struct {
+ DateOfBirth time.Time `json:"date_of_birth,omitempty"`
+ Gender string `json:"gender,omitempty"`
+}
+
+type Dependent struct {
+ PatientAccountNumber string `json:"patient_account_number,omitempty"`
+ Name Name `json:"name,omitempty"`
+ DemographicInfo DemographicInfo `json:"demographic_info,omitempty"`
+}
+
+type ServiceInfo struct {
+ DateOfService time.Time `json:"date_of_service,omitempty"`
+ ServiceTypeCodes []string `json:"service_type_codes,omitempty"`
+}
diff --git a/application/viewmodel/notification.go b/application/viewmodel/notification.go
new file mode 100644
index 0000000..6d16cb8
--- /dev/null
+++ b/application/viewmodel/notification.go
@@ -0,0 +1,34 @@
+package viewmodel
+
+import "time"
+
+type Notification struct {
+ UUID string `json:"uuid"`
+ To string `json:"to"`
+ From string `json:"from"`
+ Type string `json:"type"`
+ Subject string `json:"subject"`
+ Message string `json:"message"`
+ Ride Ride `json:"ride"`
+ User User `json:"user"`
+ CreatedUser User `json:"created_user"`
+ Created time.Time `json:"create_at"`
+ MessageType string `json:"message_type"`
+ Read bool `json:"read"`
+}
+
+type Message struct {
+ DeliveryID string `json:"id"`
+ NotificationID string `json:"nid"`
+ CreateDate time.Time `json:"date"`
+ Read bool `json:"readed"`
+ Content MessageContent `json:"content"`
+}
+
+type MessageContent struct {
+ Type string `json:"type"`
+ Subject string `json:"subject"`
+ Content string `json:"body,omitempty"`
+ Payload interface{} `json:"payload,omitempty"`
+ RedirectLink string `json:"redirect,omitempty"`
+}
diff --git a/application/viewmodel/organization.go b/application/viewmodel/organization.go
new file mode 100644
index 0000000..199bca1
--- /dev/null
+++ b/application/viewmodel/organization.go
@@ -0,0 +1,69 @@
+package viewmodel
+
+import (
+ "time"
+)
+
+type OrganizationType struct {
+ ID int64 `json:"-"`
+ Name string `json:"name"`
+ Key string `json:"key"`
+ Description string `json:"desc,omitempty"`
+ Created time.Time `json:"-"`
+ Updated time.Time `json:"-"`
+}
+
+type Organization struct {
+ ID int64 `json:"-"`
+ UUID string `json:"id"`
+ Type OrganizationType `json:"type"`
+ Name string `json:"name"`
+ Description string `json:"desc,omitempty"`
+ ReferenceID int64 `json:"-"`
+ ParentID int64 `json:"-"`
+ Main bool `json:"main"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
+ Active bool `json:"active"`
+ Blocked bool `json:"blocked"`
+ Suspended bool `json:"suspended"`
+ Author User `json:"author"`
+ LastEditor User `json:"last_editor"`
+ Contacts []OrganizationContact `json:"contacts"`
+ Addresses []OrganizationAddress `json:"addresses"`
+ ChildOrgs []Organization `json:"childs,omitempty"`
+ Parent *Organization `json:"parent,omitempty"`
+ Reference interface{} `json:"reference,omitempty"`
+}
+
+type OrganizationContact struct {
+ ID int64 `json:"-"`
+ UUID string `json:"id"`
+ Organization *Organization `json:"organization,omitempty"`
+ Type ContactType `json:"type"`
+ Contact string `json:"contact"`
+ Name string `json:"name"`
+ Description string `json:"desc"`
+ Created time.Time `json:"created"`
+ CreatedUser User `json:"author"`
+ Updated time.Time `json:"updated"`
+ UpdatedUser User `json:"last_editor"`
+ Active bool `json:"active"`
+}
+
+type OrganizationAddress struct {
+ ID int64 `json:"-"`
+ UUID string `json:"id"`
+ Organization *Organization `json:"organization,omitempty"`
+ InternalID string `json:"internal_id"`
+ Name string `json:"name"`
+ Address string `json:"address"`
+ Description string `json:"desc"`
+ Latitude float64 `json:"lat"`
+ Longitude float64 `json:"long"`
+ Created time.Time `json:"created"`
+ CreatedUser User `json:"author"`
+ Updated time.Time `json:"updated"`
+ UpdatedUser User `json:"last_editor"`
+ Active bool `json:"active"`
+}
diff --git a/application/viewmodel/pagination.go b/application/viewmodel/pagination.go
new file mode 100644
index 0000000..b485f9e
--- /dev/null
+++ b/application/viewmodel/pagination.go
@@ -0,0 +1,15 @@
+package viewmodel
+
+// ReturnPagination holds the pagination data result
+type ReturnPagination struct {
+ TotalRecords int64 `json:"total_records"`
+ RecordsPerPage int64 `json:"records_per_page"`
+ TotalPages int64 `json:"total_pages"`
+ CurrentPage int64 `json:"current_page"`
+}
+
+// PaginatedResult is the standard paginated list result
+type PaginatedResult struct {
+ Pagination ReturnPagination `json:"pagination,omitempty"`
+ List interface{} `json:"data,omitempty"`
+}
diff --git a/application/viewmodel/profile.go b/application/viewmodel/profile.go
new file mode 100644
index 0000000..53b8c20
--- /dev/null
+++ b/application/viewmodel/profile.go
@@ -0,0 +1,17 @@
+package viewmodel
+
+import "time"
+
+type Profile struct {
+ ID int64 `json:"-"`
+ Name string `json:"name"`
+ Key string `json:"key"`
+ Description string `json:"desc"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
+ Active bool `json:"active"`
+ Blocked bool `json:"blocked"`
+ Suspended bool `json:"suspended"`
+ Visible bool `json:"visible"`
+ Organization Organization `json:"organization"`
+}
diff --git a/application/viewmodel/provider.go b/application/viewmodel/provider.go
new file mode 100644
index 0000000..1fd4d2d
--- /dev/null
+++ b/application/viewmodel/provider.go
@@ -0,0 +1,119 @@
+package viewmodel
+
+type ProviderResp struct {
+ ProviderUUID string `json:"provider_uuid,omitempty"`
+ InternalID string `json:"internal_id,omitempty"`
+ InternalSuffixID string `json:"internal_suffix_id,omitempty"`
+ MukID string `json:"muk_id,omitempty"`
+ OrganizatioName string `json:"org_name,omitempty"`
+ Gender string `json:"gender,omitempty"`
+ AcceptNewPatients string `json:"accept_new_patients,omitempty"`
+ Name string `json:"name,omitempty"`
+ FirstName string `json:"first,omitempty"`
+ MiddleName string `json:"middle,omitempty"`
+ LastName string `json:"last,omitempty"`
+ Title string `json:"title,omitempty"`
+ Keys []ProviderKey `json:"keys,omitempty"`
+ Address ProviderAddress `json:"address,omitempty"`
+ Distance float64 `json:"distance,omitempty"`
+}
+
+type ProviderKey struct {
+ InternalID string `json:"internal_id"`
+ InternalSuffixID string `json:"internal_suffix_id"`
+ LocationSeqNumber string `json:"location_seq_number"`
+ PlanCode string `json:"plan_code"`
+ ProductID string `json:"product_id"`
+ TreatmentCategoryCode string `json:"treatment_category_code"`
+}
+
+type ProviderAddress struct {
+ StreetAddress1 string `json:"street_address_1,omitempty"`
+ StreetAddress2 string `json:"street_address_2,omitempty"`
+ CityName string `json:"city,omitempty"`
+ State string `json:"state,omitempty"`
+ ZipCode string `json:"zipcode,omitempty"`
+ Country string `json:"country,omitempty"`
+ Latitude float64 `json:"lat,omitempty"`
+ Longitude float64 `json:"long,omitempty"`
+ PhoneNumber string `json:"phone_number,omitempty"`
+}
+
+// ProviderSearchParams entity data
+type ProviderSearchParams struct {
+ Name string
+ SearchBy string
+ Latitude float64
+ Longitude float64
+ Distance int64
+ Limit int64
+}
+
+type ProviderResponse struct {
+ MukID string `json:"mukId"`
+ FivePartKeyGroups []PartKeyGroup `json:"fivePartKeyGroups"`
+ OrgName string `json:"orgName"`
+ Gender string `json:"gender"`
+ AcceptNewPatients string `json:"acceptNewPatients"`
+ ProviderName string `json:"providerName"`
+ FirstName string `json:"firstName"`
+ LastName string `json:"lastName"`
+ MiddleName string `json:"middleName"`
+ ProviderTitle string `json:"providerTitle"`
+ StreetName1 string `json:"streetName_1"`
+ StreetName2 string `json:"streetName_2"`
+ CityName string `json:"cityName"`
+ State string `json:"state"`
+ ZipCode string `json:"zipCode"`
+ Country string `json:"country"`
+ Latitude string `json:"latitude"`
+ Longitude string `json:"longitude"`
+ PhoneNumber string `json:"phoneNumber"`
+ ProviderEntityName string `json:"providerEntityName"`
+ ProviderEntityCode string `json:"providerEntityCode"`
+ ProviderTypeCode []ProviderTypeCode `json:"providerTypeCode"`
+ Distance string `json:"distance"`
+ AvailabilityOfCost string `json:"availabilityOfCost"`
+ TDDPhoneNumber string `json:"tddPhoneNumber"`
+ ExtendedOfficeHours string `json:"extendedOfficeHours"`
+ ProviderCountyCode string `json:"providerCountyCode"`
+ ProviderCountyName string `json:"providerCountyName"`
+ HospitalAffiliationNames []HospitalAffiliationNames `json:"hospitalAffiliationNames"`
+ ProviderAffiliationNumber string `json:"providerAffiliationNumber"`
+ ProviderAffiliationName string `json:"providerAffiliationName"`
+ LanguagesSpoken []Languages `json:"languagesSpoken"`
+ OfficeLanguagesSpoken []Languages `json:"officeLanguagesSpoken"`
+ MedSchool string `json:"medSchool"`
+ MedSchoolYear string `json:"medSchoolYear"`
+ Internship string `json:"internship"`
+ Residence string `json:"residency"`
+ Specialty1 string `json:"specialty1"`
+ Specialty2 string `json:"specialty2"`
+ Specialty3 string `json:"specialty3"`
+ Specialty4 string `json:"specialty4"`
+ Certification1 string `json:"certification1"`
+ Certification2 string `json:"certification2"`
+ Certification3 string `json:"certification3"`
+ Certification4 string `json:"certification4"`
+}
+
+type HospitalAffiliationNames struct {
+ HospAffProvOrgName string `json:"hospAffProvOrgName"`
+}
+
+type Languages struct {
+ Code string `json:"code"`
+}
+
+type ProviderTypeCode struct {
+ Code string `json:"code"`
+}
+
+type PartKeyGroup struct {
+ ProviderNum string `json:"providerNum"`
+ ProviderNumSuffix string `json:"providerNumSuffix"`
+ LocationSeqNum string `json:"locationSeqNum"`
+ PlanCode string `json:"planCode"`
+ ProductID string `json:"productId"`
+ TreatmentCategoryCode string `json:"treatmentCategoryCode"`
+}
diff --git a/application/viewmodel/tnc.go b/application/viewmodel/tnc.go
new file mode 100644
index 0000000..e5cefbf
--- /dev/null
+++ b/application/viewmodel/tnc.go
@@ -0,0 +1,161 @@
+package viewmodel
+
+import "time"
+
+//WebhookResponse has the data and events from the webhook
+type WebhookResponse struct {
+ EventID string `json:"event_id,omitempty"`
+ HREF string `json:"href,omitempty"`
+ OccurredAt string `json:"occurred_at,omitempty"`
+ EventType string `json:"event_type,omitempty"`
+ Event RideRequest `json:"event,omitempty"`
+ Ride Ride `json:"-"`
+}
+
+//RideRequest has the data to dispatch a ride
+type RideRequest struct {
+ UserUUID string `json:"user_uuid,omitempty"`
+ Status string `json:"status,omitempty"`
+ RideID string `json:"ride_id,omitempty"`
+ RideType string `json:"ride_type,omitempty"`
+ Origin Location `json:"origin,omitempty"`
+ Location Location `json:"location,omitempty"`
+ Destination Location `json:"destination,omitempty"`
+ Passenger UserLyft `json:"passenger,omitempty"`
+ Notes string `json:"external_note,omitempty"`
+ RouteURL string `json:"route_url,omitempty"`
+ ScheduledPickupRange interface{} `json:"scheduled_pickup_range,omitempty"`
+ PrimetimePercentage string `json:"primetime_percentage,omitempty"`
+ Pickup Location `json:"pickup,omitempty"`
+ DropOff Location `json:"dropoff,omitempty"`
+ Vehicle Vehicle `json:"vehicle,omitempty"`
+ Price Price `json:"price,omitempty"`
+ Driver UserLyft `json:"driver,omitempty"`
+ GeneratedAtMS *int64 `json:"generated_at_ms,omitempty"`
+ GeneratedAt *time.Time `json:"generated_at,omitempty"`
+ RequestAtMS *int64 `json:"requested_at_ms,omitempty"`
+ RequestAt *time.Time `json:"requested_at,omitempty"`
+ LineItems []Price `json:"line_items,omitempty"`
+ BeaconColor string `json:"beacon_color,omitempty"`
+ Charges []Charge `json:"charges,omitempty"`
+ VisitDate *time.Time `json:"visit_date,omitempty"`
+ VisitTime *time.Time `json:"visit_time,omitempty"`
+ PickupTime *time.Time `json:"pickup_time,omitempty"`
+ ReturnTime *time.Time `json:"return_time,omitempty"`
+ Distance float64 `json:"distance,omitempty"`
+ ETA int64 `json:"eta,omitempty"`
+ Duration int64 `json:"duration,omitempty"`
+ Visit Visit `json:"visit,omitempty"`
+ CreateUserUUID string `json:"created_user_uuid,omitempty"`
+ VisitExternalID string `json:"visit_external_id,omitempty"`
+ CanCancel []string `json:"can_cancel,omitempty"`
+ PricingDetailsURL string `json:"pricing_details_url,omitempty"`
+ RideProfile string `json:"ride_profile,omitempty"`
+ DistanceInMiles float64 `json:"distance_miles,omitempty"`
+ DurationInSeconds float64 `json:"duration_seconds,omitempty"`
+ CanceledBy string `json:"canceled_by,omitempty"`
+ TripType TripType `json:"trip_type,omitempty"`
+ Error string `json:"error,omitempty"`
+ ErrorDescription string `json:"error_description,omitempty"`
+}
+
+//Charge information
+type Charge struct {
+ Currency string `json:"currency,omitempty"`
+ PaymentMethod string `json:"payment_method,omitempty"`
+ Amount int64 `json:"amount,omitempty"`
+}
+
+//Price information
+type Price struct {
+ Currency string `json:"currency,omitempty"`
+ Amount float64 `json:"amount,omitempty"`
+ Description string `json:"description,omitempty"`
+ Type string `json:"type,omitempty"`
+}
+
+//Vehicle information
+type Vehicle struct {
+ Color string `json:"color,omitempty"`
+ Make string `json:"make,omitempty"`
+ LicensePlate string `json:"license_plate,omitempty"`
+ ImageURL string `json:"image_url,omitempty"`
+ Year int64 `json:"year,omitempty"`
+ LicensePlateState string `json:"license_plate_state,omitempty"`
+ Model string `json:"model,omitempty"`
+}
+
+//Location has the coordinates from the user
+type Location struct {
+ ID string `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Latitude float64 `json:"lat,omitempty"`
+ Longitude float64 `json:"lng,omitempty"`
+ Address string `json:"address,omitempty"`
+ ETASeconds *int64 `json:"eta_seconds,omitempty"`
+ TimeMS *int64 `json:"time_ms,omitempty"`
+ Time *time.Time `json:"time,omitempty"`
+ Bearing *float64 `json:"bearing,omitempty"`
+}
+
+//UserLyft has the personal information
+type UserLyft struct {
+ UserID *string `json:"user_id,omitempty"`
+ Rating *string `json:"rating,omitempty"`
+ ImageURL *string `json:"image_url,omitempty"`
+ FirstName string `json:"first_name,omitempty"`
+ LastName string `json:"last_name,omitempty"`
+ PhoneNumber string `json:"phone_number,omitempty"`
+}
+
+// Ride entity data
+type Ride struct {
+ UUID string `json:"ride_uuid,omitempty"`
+ InternalID string `json:"internal_id,omitempty"`
+ User User `json:"user,omitempty"`
+ Status RideStatus `json:"status,omitempty"`
+ Type RideType `json:"type,omitempty"`
+ Note string `json:"notes,omitempty"`
+ Passenger UserLyft `json:"passenger,omitempty"`
+ Driver UserLyft `json:"driver,omitempty"`
+ Vehicle Vehicle `json:"vehicle,omitempty"`
+ Route RideRoute `json:"route,omitempty"`
+ VisitDate *time.Time `json:"visit_date,omitempty"`
+ VisitTime *time.Time `json:"visit_time,omitempty"`
+ PickupTime *time.Time `json:"pickup_time,omitempty"`
+ Visit Visit `json:"visit,omitempty"`
+ CreatedUser User `json:"created_user,omitempty"`
+ CreateAt time.Time `json:"create_at,omitempty"`
+ UpdateAt time.Time `json:"update_at,omitempty"`
+ TripType TripType `json:"trip_type,omitempty"`
+}
+
+// RideStatus entity data
+type RideStatus struct {
+ Key string `json:"key,omitempty"`
+ Value string `json:"value,omitempty"`
+}
+
+// TripType entity data
+type TripType struct {
+ Key string `json:"key"`
+ Value string `json:"value"`
+}
+
+// RideType entity data
+type RideType struct {
+ Key string `json:"key,omitempty"`
+ Value string `json:"value,omitempty"`
+}
+
+// RideRoute entity data
+type RideRoute struct {
+ Origin Location `json:"origin,omitempty"`
+ Destination Location `json:"destination,omitempty"`
+ Location Location `json:"location,omitempty"`
+ RouteKML *string `json:"route_kml,omitempty"`
+ Distance float64 `json:"distance,omitempty"`
+ Duration int64 `json:"duration,omitempty"`
+ ETA int64 `json:"eta,omitempty"`
+ Bearing int64 `json:"bearing,omitempty"`
+}
diff --git a/application/viewmodel/twillio.go b/application/viewmodel/twillio.go
new file mode 100644
index 0000000..877b24e
--- /dev/null
+++ b/application/viewmodel/twillio.go
@@ -0,0 +1,87 @@
+package viewmodel
+
+type ListNumbers struct {
+ AvailableNumbers []Number `json:"available_phone_numbers,omitempty"`
+ Page int64 `json:"page,omitempty"`
+ PageSize int64 `json:"page_size,omitempty"`
+ URI string `json:"uri,omitempty"`
+ FirstPageURI string `json:"first_page_uri,omitempty"`
+ PreviousPageURI string `json:"previous_page_uri,omitempty"`
+ NextPageURI string `json:"next_page_uri,omitempty"`
+ IncomingPhones []Number `json:"incoming_phone_numbers,omitempty"`
+}
+
+type Number struct {
+ SID *string `json:"sid,omitempty"`
+ AccountSID *string `json:"account_sid,omitempty"`
+ FriendlyName string `json:"friendly_name,omitempty"`
+ PhoneNumber string `json:"phone_number,omitempty"`
+ Lata string `json:"lata,omitempty"`
+ RateCenter string `json:"rate_center,omitempty"`
+ Latitude string `json:"latitude,omitempty"`
+ Longitude string `json:"longitude,omitempty"`
+ Region string `json:"region,omitempty"`
+ PostalCode string `json:"postal_code,omitempty"`
+ ISOCountry string `json:"iso_country,omitempty"`
+ Beta bool `json:"beta,omitempty"`
+ Capabilities Capabilities `json:"capabilities,omitempty"`
+ VoiceURL *string `json:"voice_url,omitempty"`
+ VoiceMethod *string `json:"voice_method,omitempty"`
+ VoiceFallbackURL *string `json:"voice_fallback_url,omitempty"`
+ VoiceFallbackMethod *string `json:"voice_fallback_method,omitempty"`
+ VoiceCallerIDLookup bool `json:"voice_caller_id_lookup,omitempty"`
+ VoiceApplicationSID *string `json:"voice_application_sid,omitempty"`
+ DateCreated *string `json:"date_created,omitempty"`
+ DateUpdated *string `json:"date_updated,omitempty"`
+ SmsURL *string `json:"sms_url,omitempty"`
+ SmsMethod *string `json:"sms_method,omitempty"`
+ SmsFallbackURL *string `json:"sms_fallback_url,omitempty"`
+ SmsFallbackMethod *string `json:"sms_fallback_method,omitempty"`
+ SmsApplicationID *string `json:"sms_application_sid,omitempty"`
+ StatusCallback *string `json:"status_callback,omitempty"`
+ StatusCallbackMethod *string `json:"status_callback_method,omitempty"`
+ APIVersion *string `json:"api_version,omitempty"`
+}
+
+type Capabilities struct {
+ Voice bool `json:"voice,omitempty"`
+ SMS bool `json:"SMS,omitempty"`
+ MMS bool `json:"MMS,omitempty"`
+}
+
+type ProxyNumber struct {
+ From string `json:"from,omitempty"`
+ To string `json:"to,omitempty"`
+ Proxy string `json:"proxy,omitempty"`
+ Number Number `json:"details,omitempty"`
+}
+
+type SocketMessage struct {
+ From string `json:"from"`
+ To string `json:"to"`
+ Message string `json:"message"`
+ Filled bool `json:"-"`
+}
+
+type TwilioWebhook struct {
+ ToCountry string `json:"ToCountry,omitempty"`
+ ToState string `json:"ToState,omitempty"`
+ SMSMessageSID string `json:"SmsMessageSid,omitempty"`
+ NumMedia string `json:"NumMedia,omitempty"`
+ ToCity string `json:"ToCity,omitempty"`
+ FromZip string `json:"FromZip,omitempty"`
+ SMSSID string `json:"SmsSid,omitempty"`
+ FromState string `json:"FromState,omitempty"`
+ SMSStatus string `json:"SmsStatus,omitempty"`
+ FromCity string `json:"FromCity,omitempty"`
+ Body string `json:"Body,omitempty"`
+ FromCountry string `json:"FromCountry,omitempty"`
+ To string `json:"To,omitempty"`
+ ToZip string `json:"ToZip,omitempty"`
+ AddOns string `json:"AddOns,omitempty"`
+ NumSegments string `json:"NumSegments,omitempty"`
+ MessageSID string `json:"MessageSid,omitempty"`
+ AccountSID string `json:"AccountSid,omitempty"`
+ From string `json:"From,omitempty"`
+ APIVersion string `json:"ApiVersion,omitempty"`
+}
diff --git a/application/viewmodel/user.go b/application/viewmodel/user.go
new file mode 100644
index 0000000..1242485
--- /dev/null
+++ b/application/viewmodel/user.go
@@ -0,0 +1,36 @@
+package viewmodel
+
+import "time"
+
+// User model for API binding
+type User struct {
+ ID string `json:"useruuid"`
+ Name string `json:"name,omitempty"`
+ First string `json:"first,omitempty"`
+ Last string `json:"last,omitempty"`
+ Gender *string `json:"gender,omitempty"`
+ Member *string `json:"member,omitempty"`
+ BirthDate *time.Time `json:"birthdate,omitempty"`
+ Email *string `json:"email,omitempty"`
+ PhoneNumber *string `json:"phonenumber,omitempty"`
+ Pass string `json:"pass,omitempty"`
+ Active bool `json:"active,omitempty"`
+ Created time.Time `json:"created,omitempty"`
+ Updated time.Time `json:"updated,omitempty"`
+ Contacts []Contact `json:"contacts,omitempty"`
+ Rides []Ride `json:"rides,omitempty"`
+ Addresses []Address `json:"addresses,omitempty"`
+ Profiles []Profile `json:"profiles,omitempty"`
+ Types []OrganizationType `json:"types,omitempty"`
+ Organizations []Organization `json:"organizations,omitempty"`
+}
+
+type Contact struct {
+ Type ContactType `json:"type,omitempty"`
+ Value string `json:"contact,omitempty"`
+}
+
+type ContactType struct {
+ Key string `json:"key,omitempty"`
+ Value string `json:"value,omitempty"`
+}
diff --git a/application/viewmodel/visit.go b/application/viewmodel/visit.go
new file mode 100644
index 0000000..4f4317e
--- /dev/null
+++ b/application/viewmodel/visit.go
@@ -0,0 +1,33 @@
+package viewmodel
+
+import (
+ "time"
+)
+
+// VisitStatus entity data
+type VisitStatus struct {
+ Key string `json:"key,omitempty"`
+ Value string `json:"value,omitempty"`
+}
+
+// Visit entity data
+type Visit struct {
+ UUID string `json:"visit_uuid,omitempty"`
+ Status VisitStatus `json:"visit_status,omitempty"`
+ User User `json:"user,omitempty"`
+ VisitDatetime time.Time `json:"visit_datetime,omitempty"`
+ VisitDuration int64 `json:"visit_duration,omitempty"`
+ PickupDatetime time.Time `json:"pickup_datetime,omitempty"`
+ Notes *string `json:"notes,omitempty"`
+ PickupAddressID int64 `json:"pickup_address_id,omitempty"`
+ DestinationAddressID int64 `json:"destination_address_id,omitempty"`
+ Pickup Location `json:"pickup,omitempty"`
+ Provider ProviderResp `json:"provider,omitempty"`
+ CreatedUser User `json:"created_user,omitempty"`
+ CreatedDate time.Time `json:"created,omitempty"`
+ UpdatedDate time.Time `json:"updated,omitempty"`
+ ReturnDate *time.Time `json:"return_date,omitempty"`
+ TripType TripType `json:"trip_type,omitempty"`
+ ExternalID string `json:"visit_external_id,omitempty"`
+ Rides []Ride `json:"rides,omitempty"`
+}
diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml
new file mode 100644
index 0000000..044ba8c
--- /dev/null
+++ b/bitbucket-pipelines.yml
@@ -0,0 +1,59 @@
+image: golang:1.9.2
+pipelines:
+ branches:
+ master:
+ - step:
+ script:
+ - curl https://glide.sh/get | sh
+ - mkdir -p /go/src/bitbucket.org/nemt/nemt-portal-api
+ - pwd
+ - ls -al
+ - cp -R ./* /go/src/bitbucket.org/nemt/nemt-portal-api/
+ - cd /go/src/bitbucket.org/nemt/nemt-portal-api/
+ - rm -rf glide.lock
+ - rm -rf vendor/
+ - glide install -force
+ - go build -o nemt-portal-api
+ - mkdir -p dist/{static,docs}
+ - cp nemt-portal-api ./dist/
+ - cp -R static/* ./dist/static/
+ - cp -R docs/swagger/ ./dist/docs/
+ - cp config.prd.toml ./dist/config.toml
+ - docker build -f Dockerfile.run -t nemt-portal-api-run:prod --force-rm --build-arg BIN_NAME=nemt-portal-api --build-arg APP_NAME=nemt-portal-api .
+ - apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
+ - apt-get install python3-pip -y
+ - pip3 install --upgrade awscli
+ - eval $(aws ecr get-login --no-include-email --region us-east-2)
+ - docker tag nemt-portal-api-run:prod 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:prod
+ - docker push 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:prod
+ - eval $(aws --region us-east-2 ecs register-task-definition --cli-input-json file://ecs.prd.json >/dev/null)
+ - eval $(aws --region us-east-2 ecs update-service --cluster App --service portal-api --task-definition portal-api-prod >/dev/null)
+ development:
+ - step:
+ script:
+ - curl https://glide.sh/get | sh
+ - mkdir -p /go/src/bitbucket.org/nemt/nemt-portal-api
+ - pwd
+ - ls -al
+ - cp -R ./* /go/src/bitbucket.org/nemt/nemt-portal-api/
+ - cd /go/src/bitbucket.org/nemt/nemt-portal-api/
+ - rm -rf glide.lock
+ - rm -rf vendor/
+ - glide install -force
+ - go build -o nemt-portal-api
+ - mkdir -p dist/{static,docs}
+ - cp nemt-portal-api ./dist/
+ - cp -R static/* ./dist/static/
+ - cp -R docs/swagger/ ./dist/docs/
+ - cp config.stg.toml ./dist/config.toml
+ - docker build -f Dockerfile.run -t nemt-portal-api-run:dev --force-rm --build-arg BIN_NAME=nemt-portal-api --build-arg APP_NAME=nemt-portal-api .
+ - apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
+ - apt-get install python3-pip -y
+ - pip3 install --upgrade awscli
+ - eval $(aws ecr get-login --no-include-email --region us-east-2)
+ - docker tag nemt-portal-api-run:dev 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:dev
+ - docker push 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:dev
+ - eval $(aws --region us-east-2 ecs register-task-definition --cli-input-json file://ecs.stg.json >/dev/null)
+ - eval $(aws --region us-east-2 ecs update-service --cluster NemtCluster2 --service portal-api --task-definition portal-api-dev >/dev/null)
+options:
+ docker: true
\ No newline at end of file
diff --git a/config.dev.toml b/config.dev.toml
new file mode 100644
index 0000000..9919890
--- /dev/null
+++ b/config.dev.toml
@@ -0,0 +1,82 @@
+[app]
+name = "nemt"
+debug = true
+
+ [app.docs]
+ swagger-path = "./static/swagger-ui"
+ yaml-path = "./docs/swagger"
+
+[db]
+host = "dbdev01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
+port = 3306
+name = "nemt"
+user = "nemt-user"
+pass = "4umQ3ENNzt"
+max-life-minutes = 5
+max-idle-conns = 5
+max-open-conns = 100
+
+[http]
+port = 5100
+prefix = "/v1"
+
+ [http.auth]
+ app-key = "8a266a40-ed2e-4be2-bdfc-459a507bf02e"
+ certificate-path = "./static/cert/nemt-portal-api.key"
+ frontend-urls = [
+ "http://localhost:3100"
+ ]
+
+[aws]
+s3-bucket = "static.nemt-portal-api.com.br/development"
+
+[cache]
+server = "internal-REDISDEV-INT-ELB01-905785815.us-east-2.elb.amazonaws.com"
+port = 6379
+db = 0
+pass = "3rdaP3KL2x%V"
+prefix = "nemt-portal-api-dev"
+default-expiration = "5m"
+
+[log]
+log-to-file = false
+path = "nemt-portal-api.log"
+
+[twilio]
+account = "AC3106c1aeb2c74b7e45adc1ba0ff8c6e2"
+token = "36ba77236be5eb5848b3746e4400f4e2"
+sender = "+17084261667"
+twiml-sid = "APc33ccb8af94ecf3d61c6bfd9a7f69749"
+
+[email]
+server = "email-smtp.us-east-1.amazonaws.com"
+port = 587
+user = "AKIAIP2QTIHICY5I5BBA"
+pass = "AkInsFK64iCbrAftVnVGFVVJOcMIG/pv8k1aFZwAQ5lF"
+sender = "no-reply@chmhub.com"
+
+[google-shortener]
+client-id = "1059812138553-t7jents4d3a7uqpb9ms9nf2luqkqplrt.apps.googleusercontent.com"
+secret-key = "r478-RtEmvAcDWlLQk1CZatQ"
+api-key = "AIzaSyAQsoEaUmg96-TxxNCTJhyu5HEOLBzxcCw"
+
+[lyft]
+key = "KkS0DgSPuJ84"
+secret = "SANDBOX-8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
+token = "UyjcHl7fC6LxRWgZ8I6-_LJ0_j6YcWNg9ct2xEXMdX2iRiGrMrjrbJmxtPlNPGvN"
+
+[lyft-prod]
+key = "KkS0DgSPuJ84"
+secret = "8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
+token = "Xa8n7M8TQ62iRpElan0gaPZwaPzUIa85G-epIesWJysJgOQU5zRDLdqD1ygZk8-Y"
+user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
+
+[bxe]
+url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
+key = "dacg7jtsmb6ajr3z553jbczg"
+secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
+
+[blue365]
+url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
+key = "jcn5xjxvarc96rtjxp25dctj"
+secret = "6XdEusG2w2PWWXsfXVyweQnY"
\ No newline at end of file
diff --git a/config.prd.toml b/config.prd.toml
new file mode 100644
index 0000000..d8309e8
--- /dev/null
+++ b/config.prd.toml
@@ -0,0 +1,82 @@
+[app]
+name = "nemt"
+debug = true
+
+ [app.docs]
+ swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
+ yaml-path = "/opt/app/nemt-portal-api/docs/swagger"
+
+[db]
+host = "db01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
+port = 3306
+name = "nemt_clean"
+user = "nemt-user"
+pass = "OL&!n#p6J8Lu"
+max-life-minutes = 5
+max-idle-conns = 5
+max-open-conns = 100
+
+[http]
+port = 5100
+prefix = "/v1"
+
+ [http.auth]
+ app-key = "8a266a40-ed2e-4be2-bdfc-459a507bf02e"
+ certificate-path = "/opt/app/static/cert/nemt-portal-api.key"
+ frontend-urls = [
+ "http://localhost:3100"
+ ]
+
+[aws]
+s3-bucket = "static.nemt-portal-api.com.br/prod"
+
+[cache]
+server = "internal-REDIS-INT-ELB01-661255167.us-east-2.elb.amazonaws.com"
+port = 6379
+db = 0
+pass = "3rdaP3KL2x%V"
+prefix = "portal-api-prod"
+default-expiration = "5m"
+
+[log]
+log-to-file = false
+path = "nemt-portal-api.log"
+
+[twilio]
+account = "AC3106c1aeb2c74b7e45adc1ba0ff8c6e2"
+token = "36ba77236be5eb5848b3746e4400f4e2"
+sender = "+17084261667"
+twiml-sid = "APc33ccb8af94ecf3d61c6bfd9a7f69749"
+
+[email]
+server = "email-smtp.us-east-1.amazonaws.com"
+port = 587
+user = "AKIAIP2QTIHICY5I5BBA"
+pass = "AkInsFK64iCbrAftVnVGFVVJOcMIG/pv8k1aFZwAQ5lF"
+sender = "no-reply@chmhub.com"
+
+[google-shortener]
+client-id = "1059812138553-t7jents4d3a7uqpb9ms9nf2luqkqplrt.apps.googleusercontent.com"
+secret-key = "r478-RtEmvAcDWlLQk1CZatQ"
+api-key = "AIzaSyAQsoEaUmg96-TxxNCTJhyu5HEOLBzxcCw"
+
+[lyft]
+key = "KkS0DgSPuJ84"
+secret = "SANDBOX-8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
+token = "UyjcHl7fC6LxRWgZ8I6-_LJ0_j6YcWNg9ct2xEXMdX2iRiGrMrjrbJmxtPlNPGvN"
+
+[lyft-prod]
+key = "KkS0DgSPuJ84"
+secret = "8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
+token = "Xa8n7M8TQ62iRpElan0gaPZwaPzUIa85G-epIesWJysJgOQU5zRDLdqD1ygZk8-Y"
+user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
+
+[bxe]
+url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
+key = "dacg7jtsmb6ajr3z553jbczg"
+secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
+
+[blue365]
+url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
+key = "jcn5xjxvarc96rtjxp25dctj"
+secret = "6XdEusG2w2PWWXsfXVyweQnY"
diff --git a/config.stg.toml b/config.stg.toml
new file mode 100644
index 0000000..050b811
--- /dev/null
+++ b/config.stg.toml
@@ -0,0 +1,82 @@
+[app]
+name = "nemt"
+debug = true
+
+ [app.docs]
+ swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
+ yaml-path = "/opt/app/nemt-portal-api/docs/swagger"
+
+[db]
+host = "dbdev01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
+port = 3306
+name = "nemt"
+user = "nemt-user"
+pass = "4umQ3ENNzt"
+max-life-minutes = 5
+max-idle-conns = 5
+max-open-conns = 100
+
+[http]
+port = 5100
+prefix = "/v1"
+
+ [http.auth]
+ app-key = "8a266a40-ed2e-4be2-bdfc-459a507bf02e"
+ certificate-path = "/opt/app/static/cert/nemt-portal-api.key"
+ frontend-urls = [
+ "http://localhost:3100"
+ ]
+
+[aws]
+s3-bucket = "static.nemt-portal-api.com.br/staging"
+
+[cache]
+server = "internal-REDISDEV-INT-ELB01-905785815.us-east-2.elb.amazonaws.com"
+port = 6379
+db = 0
+pass = "3rdaP3KL2x%V"
+prefix = "portal-api-test"
+default-expiration = "5m"
+
+[log]
+log-to-file = false
+path = "nemt-portal-api.log"
+
+[twilio]
+account = "AC3106c1aeb2c74b7e45adc1ba0ff8c6e2"
+token = "36ba77236be5eb5848b3746e4400f4e2"
+sender = "+17084261667"
+twiml-sid = "APc33ccb8af94ecf3d61c6bfd9a7f69749"
+
+[email]
+server = "email-smtp.us-east-1.amazonaws.com"
+port = 587
+user = "AKIAIP2QTIHICY5I5BBA"
+pass = "AkInsFK64iCbrAftVnVGFVVJOcMIG/pv8k1aFZwAQ5lF"
+sender = "no-reply@chmhub.com"
+
+[google-shortener]
+client-id = "1059812138553-t7jents4d3a7uqpb9ms9nf2luqkqplrt.apps.googleusercontent.com"
+secret-key = "r478-RtEmvAcDWlLQk1CZatQ"
+api-key = "AIzaSyAQsoEaUmg96-TxxNCTJhyu5HEOLBzxcCw"
+
+[lyft]
+key = "KkS0DgSPuJ84"
+secret = "SANDBOX-8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
+token = "UyjcHl7fC6LxRWgZ8I6-_LJ0_j6YcWNg9ct2xEXMdX2iRiGrMrjrbJmxtPlNPGvN"
+
+[lyft-prod]
+key = "KkS0DgSPuJ84"
+secret = "8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
+token = "Xa8n7M8TQ62iRpElan0gaPZwaPzUIa85G-epIesWJysJgOQU5zRDLdqD1ygZk8-Y"
+user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
+
+[bxe]
+url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
+key = "dacg7jtsmb6ajr3z553jbczg"
+secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
+
+[blue365]
+url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
+key = "jcn5xjxvarc96rtjxp25dctj"
+secret = "6XdEusG2w2PWWXsfXVyweQnY"
diff --git a/data/data.go b/data/data.go
new file mode 100644
index 0000000..a366741
--- /dev/null
+++ b/data/data.go
@@ -0,0 +1,11 @@
+package data
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/data/datamysql"
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+)
+
+func Connect(cfg *config.Config) (contract.DataManager, error) {
+ return datamysql.Instance(cfg)
+}
diff --git a/data/datamysql/datamysql.go b/data/datamysql/datamysql.go
new file mode 100644
index 0000000..7ac8d6f
--- /dev/null
+++ b/data/datamysql/datamysql.go
@@ -0,0 +1,133 @@
+package datamysql
+
+import (
+ "database/sql"
+ "fmt"
+ "sync"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/go-sql-driver/mysql"
+)
+
+var (
+ instance *Conn
+ once sync.Once
+ connErr error
+)
+
+// Conn is the MySQL connection manager
+type Conn struct {
+ db *sql.DB
+ users *userRepo
+ rides *rideRepo
+ visit *visitRepo
+ provider *providerRepo
+ notification *notificationRepo
+ profile *profileRepo
+ organization *organizationRepo
+}
+
+// Begin starts a transaction
+func (c *Conn) Begin() (contract.TransactionManager, error) {
+ tx, err := c.db.Begin()
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ return newTransaction(tx), nil
+}
+
+// Close closes the db connection
+func (c *Conn) Close() (err error) {
+ return c.db.Close()
+}
+
+// Users returns the users set
+func (c *Conn) Users() contract.UserRepo {
+ return c.users
+}
+
+// Rides returns the rides set
+func (c *Conn) Rides() contract.RideRepo {
+ return c.rides
+}
+
+// Visits returns the rides set
+func (c *Conn) Visits() contract.VisitRepo {
+ return c.visit
+}
+
+// Provider returns the rides set
+func (c *Conn) Provider() contract.ProviderRepo {
+ return c.provider
+}
+
+// Provider returns the rides set
+func (c *Conn) Profile() contract.ProfileRepo {
+ return c.profile
+}
+
+// Provider returns the rides set
+func (c *Conn) Notification() contract.NotificationRepo {
+ return c.notification
+}
+
+// Provider returns the rides set
+func (c *Conn) Organization() contract.OrganizationRepo {
+ return c.organization
+}
+
+// Instance returns an instance of a DataManager
+func Instance(cfg *config.Config) (contract.DataManager, error) {
+ once.Do(func() {
+
+ db, err := sql.Open("mysql", getMySQLConfig(cfg).FormatDSN())
+ if err != nil {
+ connErr = errors.Wrap(err)
+ return
+ }
+
+ err = db.Ping()
+ if err != nil {
+ connErr = errors.Wrap(err)
+ return
+ }
+
+ connMaxLifetime := time.Duration(cfg.DB.MaxLifeInMinutes) * time.Minute
+ db.SetConnMaxLifetime(connMaxLifetime)
+ db.SetMaxIdleConns(cfg.DB.MaxIdleConns)
+ db.SetMaxOpenConns(cfg.DB.MaxOpenConns)
+
+ instance = new(Conn)
+ instance.db = db
+
+ instance.users = newUserRepo(db)
+ instance.rides = newRideRepo(db)
+ instance.visit = newVisitRepo(db)
+ instance.provider = newProviderRepo(db)
+ instance.notification = newNotificationRepo(db)
+ instance.profile = newProfileRepo(db)
+ instance.organization = newOrganizationRepo(db)
+ })
+
+ return instance, connErr
+}
+
+// getMySQLConfig returns the configuration for MySQL driver
+func getMySQLConfig(cfg *config.Config) *mysql.Config {
+ loc, _ := time.LoadLocation("UTC")
+
+ return &mysql.Config{
+ Net: "tcp",
+ Addr: fmt.Sprintf("%s:%d", cfg.DB.Host, cfg.DB.Port),
+ DBName: cfg.DB.Name,
+ User: cfg.DB.User,
+ Passwd: cfg.DB.Pass,
+ ParseTime: true,
+ Strict: true,
+ Loc: loc,
+ }
+}
diff --git a/data/datamysql/notification.go b/data/datamysql/notification.go
new file mode 100644
index 0000000..3d5f834
--- /dev/null
+++ b/data/datamysql/notification.go
@@ -0,0 +1,140 @@
+package datamysql
+
+import (
+ "database/sql"
+ "fmt"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ uuid "github.com/satori/go.uuid"
+)
+
+// visitRepo maps methods to database
+type notificationRepo struct {
+ conn executor
+}
+
+func newNotificationRepo(conn executor) *notificationRepo {
+ return ¬ificationRepo{
+ conn: conn,
+ }
+}
+
+func (c *notificationRepo) Create(notification entity.Notification) (entity.Notification, error) {
+ const (
+ statusQuery = `SELECT a.contact_type_id, b.ride_id, c.user_id, d.user_id created_user_id FROM tab_contact_type a, tab_ride b, tab_user c, tab_user d WHERE a.key = ? AND b.ride_uuid = ? AND c.user_uuid = ? AND d.user_uuid = ?;`
+ query = `INSERT INTO tab_notification(notification_uuid, ride_id, user_id, contact_type_id, contact, message, created_user_id, readed, notificaton_type) VALUES(?, ?, ?, ?, ?, ?, ?, 0, ?);`
+ )
+
+ retVal := notification
+ UUID, _ := uuid.NewV4()
+ retVal.UUID = UUID.String()
+
+ row := c.conn.QueryRow(statusQuery, retVal.Type, retVal.Ride.UUID, retVal.User.UUID, retVal.CreatedUser.UUID)
+ if err := row.Scan(&retVal.TypeID, &retVal.Ride.ID, &retVal.User.ID, &retVal.CreatedUser.ID); err != nil {
+ fmt.Println("Error to get base data: ", err.Error())
+ return retVal, err
+ }
+
+ results, err := c.conn.Exec(query, retVal.UUID, retVal.Ride.ID, retVal.User.ID, retVal.TypeID, retVal.Subject, retVal.Message, retVal.CreatedUser.ID, retVal.MessageType)
+ if err != nil {
+ return retVal, err
+ }
+
+ retVal.ID, err = results.LastInsertId()
+ if err != nil {
+ return retVal, err
+ }
+
+ return c.GetByID(retVal.ID)
+}
+
+func (c *notificationRepo) getQuery() string {
+ return `SELECT
+ a.notification_id,
+ a.notification_uuid,
+ a.ride_id,
+ a.user_id,
+ c.user_uuid,
+ c.name user_name,
+ CASE WHEN b.key = 'sms' THEN e.phone_number WHEN b.key = 'email' THEN e.email WHEN b.key = 'app' THEN c.user_uuid END to_address,
+ CASE WHEN b.key = 'sms' THEN f.phone_number WHEN b.key = 'email' THEN f.email WHEN b.key = 'app' THEN d.user_uuid END from_address,
+ a.contact_type_id,
+ b.key contact_type_key,
+ a.contact,
+ a.message,
+ a.create_at,
+ a.readed,
+ d.user_id created_user_id,
+ d.user_uuid created_user_uuid,
+ d.name created_user_name,
+ a.notificaton_type
+ FROM
+ tab_notification a
+ INNER JOIN tab_contact_type b
+ ON a.contact_type_id = b.contact_type_id
+ INNER JOIN tab_user c
+ ON a.user_id = c.user_id
+ INNER JOIN tab_user d
+ ON a.created_user_id = d.user_id
+ INNER JOIN tab_login e
+ ON c.user_id = e.user_id
+ INNER JOIN tab_login f
+ ON d.user_id = f.user_id`
+}
+
+func (c *notificationRepo) GetLastNotificationFromPhoneNumber(notificationType string, phoneNumber string, status string) (entity.Notification, error) {
+ const (
+ whereClause = ` WHERE
+ a.notificaton_type = ?
+ AND e.phone_number = ?
+ AND b.key = ?
+ ORDER BY a.notification_id DESC
+ LIMIT 1;`
+ )
+ finalQuery := c.getQuery() + whereClause
+
+ return c.parseEntity(c.conn.QueryRow(finalQuery, notificationType, phoneNumber, status))
+}
+
+func (c *notificationRepo) GetByUserUUIDAndReadStatus(userUUID string, status string, isRead bool) ([]entity.Notification, error) {
+ return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.readed = ? AND b.key = ? AND c.user_uuid = ?; ", isRead, status, userUUID))
+}
+
+func (c *notificationRepo) GetByUserUUID(userUUID string, status string) ([]entity.Notification, error) {
+ return c.parseSet(c.conn.Query(c.getQuery()+" WHERE b.key = ? AND c.user_uuid = ?; ", status, userUUID))
+}
+
+func (c *notificationRepo) ReadStatus(notificationUUID string, isRead bool) error {
+ const query = "UPDATE tab_notification SET readed = ? WHERE notification_uuid = ?"
+ _, err := c.conn.Exec(query, isRead, notificationUUID)
+ return err
+}
+
+func (c *notificationRepo) GetByID(ID int64) (entity.Notification, error) {
+ return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.notification_id = ?; ", ID))
+}
+
+// parseSet parses a result set result to an entity array
+func (c *notificationRepo) parseSet(rows *sql.Rows, err error) ([]entity.Notification, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.Notification, 0)
+ for rows.Next() {
+ entity, err := c.parseEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *notificationRepo) parseEntity(row scanner) (retVal entity.Notification, err error) {
+ err = row.Scan(
+ &retVal.ID, &retVal.UUID, &retVal.Ride.ID, &retVal.User.ID, &retVal.User.UUID, &retVal.User.Name, &retVal.To, &retVal.From, &retVal.TypeID, &retVal.Type, &retVal.Subject, &retVal.Message, &retVal.Created, &retVal.Read, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.MessageType)
+
+ return retVal, errors.Wrap(err)
+}
diff --git a/data/datamysql/organization.go b/data/datamysql/organization.go
new file mode 100644
index 0000000..9dccc9b
--- /dev/null
+++ b/data/datamysql/organization.go
@@ -0,0 +1,482 @@
+package datamysql
+
+import (
+ "database/sql"
+ "fmt"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ uuid "github.com/satori/go.uuid"
+)
+
+// rideRepo maps methods to database
+type organizationRepo struct {
+ conn executor
+}
+
+func newOrganizationRepo(conn executor) *organizationRepo {
+ return &organizationRepo{
+ conn: conn,
+ }
+}
+
+func (c *organizationRepo) getQuery() string {
+ const (
+ query = `SELECT
+ a.organization_id,
+ a.organization_uuid,
+ b.organization_type_id,
+ b.organization_type,
+ b.organization_type_key,
+ a.organization_name,
+ a.organization_description,
+ a.organization_reference_id,
+ a.organization_parent_id,
+ (a.main_organization = b'1') main_organization,
+ a.create_at,
+ a.update_at,
+ (a.active = b'1') active,
+ (a.suspended = b'1') suspended,
+ (a.blocked = b'1') blocked,
+ c.user_id created_user_id,
+ c.user_uuid created_user_uuid,
+ c.name created_user_name,
+ d.user_id updated_user_id,
+ d.user_uuid updated_user_uuid,
+ d.name updated_user_name
+ FROM
+ tab_organization a
+ INNER JOIN tab_organization_type b
+ ON a.organization_type_id = b.organization_type_id
+ INNER JOIN tab_user c
+ ON c.user_id = a.created_user
+ INNER JOIN tab_user d
+ ON d.user_id = a.updated_user `
+ )
+
+ return query
+}
+func (c *organizationRepo) getAddressQuery() string {
+ const query = `SELECT
+ a.organization_address_id,
+ a.organization_address_uuid,
+ a.internal_id,
+ a.name,
+ a.address,
+ a.desc,
+ a.lat,
+ a.long,
+ a.created,
+ a.created_user_id,
+ c.user_uuid created_user_uuid,
+ c.name created_user_name,
+ a.updated,
+ a.updated_user_id,
+ d.user_uuid updated_user_uuid,
+ d.name updated_user_name,
+ (a.active = b'1') active
+ FROM tab_organization_address a
+ INNER JOIN tab_organization b
+ ON b.organization_id = a.organization_id
+ INNER JOIN tab_user c
+ ON c.user_id = a.created_user_id
+ INNER JOIN tab_user d
+ ON d.user_id = a.updated_user_id `
+
+ return query
+}
+
+func (c *organizationRepo) getContactQuery() string {
+ const (
+ query = `SELECT
+ a.organization_contact_id,
+ a.organization_contact_uuid,
+ b.contact_type_id,
+ b.key contact_type_key,
+ b.name contact_type_name,
+ a.contact,
+ a.contact_name,
+ a.contact_desc,
+ a.created,
+ a.created_user_id,
+ d.user_uuid created_user_uuid,
+ d.name created_user_name,
+ a.updated,
+ a.updated_user_id,
+ e.user_uuid updated_user_uuid,
+ e.name updated_user_name,
+ (a.active = b'1') active
+ FROM tab_organization_contact a
+ INNER JOIN tab_contact_type b
+ ON a.contact_type_id = b.contact_type_id
+ INNER JOIN tab_organization c
+ ON c.organization_id = a.organization_id
+ INNER JOIN tab_user d
+ ON d.user_id = a.created_user_id
+ INNER JOIN tab_user e
+ ON e.user_id = a.updated_user_id `
+ )
+
+ return query
+}
+
+func (c *organizationRepo) getTypeQuery() string {
+ const (
+ query = `SELECT
+ organization_type_id,
+ organization_type,
+ organization_type_key,
+ description,
+ create_at,
+ update_at
+ FROM
+ tab_organization_type `
+ )
+
+ return query
+}
+
+// parseSet parses a result set result to an entity array
+func (c *organizationRepo) parseSet(rows *sql.Rows, err error) ([]entity.Organization, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.Organization, 0)
+ for rows.Next() {
+ entity, err := c.parseEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *organizationRepo) parseEntity(row scanner) (retVal entity.Organization, err error) {
+ err = row.Scan(
+ &retVal.ID, &retVal.UUID, &retVal.Type.ID, &retVal.Type.Name, &retVal.Type.Key, &retVal.Name, &retVal.Description, &retVal.ReferenceID, &retVal.ParentID, &retVal.Main, &retVal.Created, &retVal.Updated, &retVal.Active, &retVal.Suspended, &retVal.Blocked, &retVal.Author.ID, &retVal.Author.UUID, &retVal.Author.Name, &retVal.LastEditor.ID, &retVal.LastEditor.UUID, &retVal.LastEditor.Name)
+
+ return retVal, errors.Wrap(err)
+}
+
+// parseSet parses a result set result to an entity array
+func (c *organizationRepo) parseContactSet(rows *sql.Rows, err error) ([]entity.OrganizationContact, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.OrganizationContact, 0)
+ for rows.Next() {
+ entity, err := c.parseContactEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *organizationRepo) parseContactEntity(row scanner) (retVal entity.OrganizationContact, err error) {
+ err = row.Scan(
+ &retVal.ID, &retVal.UUID, &retVal.Type.ID, &retVal.Type.Key, &retVal.Type.Value, &retVal.Contact, &retVal.Name, &retVal.Description, &retVal.Created, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.Updated, &retVal.UpdatedUser.ID, &retVal.UpdatedUser.UUID, &retVal.UpdatedUser.Name, &retVal.Active)
+
+ return retVal, errors.Wrap(err)
+}
+
+// parseSet parses a result set result to an entity array
+func (c *organizationRepo) parseAddressSet(rows *sql.Rows, err error) ([]entity.OrganizationAddress, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.OrganizationAddress, 0)
+ for rows.Next() {
+ entity, err := c.parseAddressEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *organizationRepo) parseAddressEntity(row scanner) (retVal entity.OrganizationAddress, err error) {
+ err = row.Scan(
+ &retVal.ID, &retVal.UUID, &retVal.InternalID, &retVal.Name, &retVal.Address, &retVal.Description, &retVal.Latitude, &retVal.Longitude, &retVal.Created, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.Updated, &retVal.UpdatedUser.ID, &retVal.UpdatedUser.UUID, &retVal.UpdatedUser.Name, &retVal.Active)
+
+ return retVal, errors.Wrap(err)
+}
+
+// parseSet parses a result set result to an entity array
+func (c *organizationRepo) parseTypeSet(rows *sql.Rows, err error) ([]entity.OrganizationType, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.OrganizationType, 0)
+ for rows.Next() {
+ entity, err := c.parseTypeEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *organizationRepo) parseTypeEntity(row scanner) (retVal entity.OrganizationType, err error) {
+ err = row.Scan(
+ &retVal.ID, &retVal.Name, &retVal.Key, &retVal.Description, &retVal.Created, &retVal.Updated)
+
+ return retVal, errors.Wrap(err)
+}
+
+func (c *organizationRepo) GetAllTypes() ([]entity.OrganizationType, error) {
+ return c.parseTypeSet(c.conn.Query(c.getTypeQuery()))
+}
+
+func (c *organizationRepo) GetTypeByKey(key string) (entity.OrganizationType, error) {
+ return c.parseTypeEntity(c.conn.QueryRow(c.getTypeQuery()+" WHERE organization_type_key=?", key))
+}
+
+func (c *organizationRepo) GetByType(organizationTypeKey string) ([]entity.Organization, error) {
+ if organizationTypeKey == "" {
+ return c.parseSet(c.conn.Query(c.getQuery()))
+ } else {
+ return c.parseSet(c.conn.Query(c.getQuery()+" WHERE b.organization_type_key = ? ", organizationTypeKey))
+ }
+}
+
+func (c *organizationRepo) GetByName(name string, searchType string) ([]entity.Organization, error) {
+ finalQuery := c.getQuery() + " WHERE a.organization_name LIKE ?"
+ switch searchType {
+ case "parent":
+ finalQuery += " AND a.organization_parent_id > 0; "
+ case "child":
+ finalQuery += " AND a.organization_parent_id = 0; "
+ }
+ name = "%" + name + "%"
+
+ fmt.Println(finalQuery)
+
+ return c.parseSet(c.conn.Query(finalQuery, name))
+}
+
+func (c *organizationRepo) GetByUUID(organizationUUID string) (entity.Organization, error) {
+ return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_uuid = ? ", organizationUUID))
+}
+
+func (c *organizationRepo) GetByID(organizationID int64) (entity.Organization, error) {
+ return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_id = ? ", organizationID))
+}
+
+func (c *organizationRepo) GetChildsByID(organizationID int64) ([]entity.Organization, error) {
+ return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.organization_parent_id = ? ", organizationID))
+}
+
+func (c *organizationRepo) GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error) {
+ return c.parseContactSet(c.conn.Query(c.getContactQuery()+" WHERE a.active = 1 AND c.organization_uuid = ? ", organizationUUID))
+}
+
+func (c *organizationRepo) GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error) {
+ return c.parseContactSet(c.conn.Query(c.getContactQuery()+" WHERE a.active = 1 AND c.organization_id = ? ", organizationID))
+}
+
+func (c *organizationRepo) GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error) {
+ return c.parseContactEntity(c.conn.QueryRow(c.getContactQuery()+" WHERE a.organization_contact_uuid = ? ", contactUUID))
+}
+
+func (c *organizationRepo) GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error) {
+ return c.parseAddressSet(c.conn.Query(c.getAddressQuery()+" WHERE a.active = 1 AND b.organization_uuid = ? ", organizationUUID))
+}
+
+func (c *organizationRepo) GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error) {
+ return c.parseAddressSet(c.conn.Query(c.getAddressQuery()+" WHERE a.active = 1 AND b.organization_id = ? ", organizationID))
+}
+
+func (c *organizationRepo) GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error) {
+ return c.parseAddressEntity(c.conn.QueryRow(c.getAddressQuery()+" WHERE a.organization_address_uuid = ? ", contactUUID))
+}
+
+func (c *organizationRepo) SetParentOrganization(organizationID int64, parentOrganizationID int64) error {
+ const (
+ query = `UPDATE tab_organization SET organization_parent_id = ? WHERE organization_id = ?;`
+ )
+
+ _, err := c.conn.Exec(query, parentOrganizationID, organizationID)
+ if err != nil {
+ return err
+ } else {
+ return nil
+ }
+}
+
+func (c *organizationRepo) InactivateOrganizationAddress(address entity.OrganizationAddress) error {
+ const (
+ query = "UPDATE tab_organization_address SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_address_uuid = ?"
+ )
+
+ if address.Organization == nil {
+ return errors.NewNotFoundError()
+ }
+
+ organization, err := c.GetByUUID(address.Organization.UUID)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.conn.Exec(query, address.UpdatedUser.ID, organization.ID, address.UUID)
+ if err != nil {
+ return err
+ } else {
+ return nil
+ }
+}
+
+func (c *organizationRepo) SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) {
+ const (
+ query = "INSERT INTO tab_organization_address(organization_address_uuid, organization_id, internal_id, `name`, address, `desc`, lat, `long`, created_user_id, updated_user_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
+ )
+
+ if address.Organization == nil {
+ return entity.OrganizationAddress{}, errors.NewNotFoundError()
+ }
+
+ organization, err := c.GetByUUID(address.Organization.UUID)
+ if err != nil {
+ return entity.OrganizationAddress{}, err
+ }
+
+ UUID, _ := uuid.NewV4()
+ result, err := c.conn.Exec(query, UUID.String(), organization.ID, address.InternalID, address.Name, address.Address, address.Description, address.Latitude, address.Longitude, address.CreatedUser.ID, address.UpdatedUser.ID)
+ if err != nil {
+ return entity.OrganizationAddress{}, err
+ }
+
+ address.ID, err = result.LastInsertId()
+ if err != nil {
+ return address, err
+ }
+
+ return address, nil
+}
+
+func (c *organizationRepo) InactivateOrganizationContact(contact entity.OrganizationContact) error {
+ const (
+ query = "UPDATE tab_organization_contact SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_contact_uuid = ?"
+ )
+
+ if contact.Organization == nil {
+ return errors.NewNotFoundError()
+ }
+
+ organization, err := c.GetByUUID(contact.Organization.UUID)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.conn.Exec(query, contact.UpdatedUser.ID, organization.ID, contact.UUID)
+ if err != nil {
+ return err
+ } else {
+ return nil
+ }
+}
+
+func (c *organizationRepo) SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) {
+ const (
+ selectQuery = "SELECT a.contact_type_id, a.name, a.key FROM tab_contact_type a WHERE a.key = ?"
+ query = "INSERT INTO tab_organization_contact(organization_contact_uuid, organization_id, contact_type_id, contact, contact_name, contact_desc, created_user_id, updated_user_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?);"
+ )
+
+ if contact.Organization == nil {
+ return entity.OrganizationContact{}, errors.NewNotFoundError()
+ }
+
+ organization, err := c.GetByUUID(contact.Organization.UUID)
+ if err != nil {
+ return entity.OrganizationContact{}, err
+ }
+
+ row := c.conn.QueryRow(selectQuery, contact.Type.Key)
+ err = row.Scan(&contact.Type.ID, &contact.Type.Value, &contact.Type.Key)
+ if err != nil {
+ return entity.OrganizationContact{}, err
+ }
+
+ UUID, _ := uuid.NewV4()
+ result, err := c.conn.Exec(query, UUID.String(), organization.ID, contact.Type.ID, contact.Contact, contact.Name, contact.Description, contact.CreatedUser.ID, contact.UpdatedUser.ID)
+ if err != nil {
+ return entity.OrganizationContact{}, err
+ }
+
+ contact.ID, err = result.LastInsertId()
+ if err != nil {
+ return contact, err
+ }
+
+ return contact, nil
+}
+
+func (c *organizationRepo) AddOrganization(organization entity.Organization) (entity.Organization, error) {
+ const (
+ queryOrgType = "SELECT a.organization_type_id FROM tab_organization_type a WHERE a.organization_type_key = ?;"
+ queryParentOrg = "SELECT a.organization_id FROM tab_organization a WHERE a.organization_uuid = ?;"
+ query = "INSERT INTO tab_organization(organization_uuid, organization_type_id, organization_name, organization_description, organization_reference_id, organization_parent_id, main_organization, created_user, updated_user) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?);"
+ )
+
+ row := c.conn.QueryRow(queryOrgType, organization.Type.Key)
+ err := row.Scan(&organization.Type.ID)
+ if err != nil {
+ return entity.Organization{}, err
+ }
+
+ if organization.Parent != nil && organization.Parent.UUID != "" {
+ row := c.conn.QueryRow(queryParentOrg, organization.Parent.UUID)
+ err := row.Scan(&organization.Parent.ID)
+ if err != nil {
+ return entity.Organization{}, err
+ }
+ organization.ParentID = organization.Parent.ID
+ }
+
+ UUID, _ := uuid.NewV4()
+ organization.UUID = UUID.String()
+ result, err := c.conn.Exec(query, organization.UUID, organization.Type.ID, organization.Name, organization.Description, organization.ReferenceID, organization.ParentID, false, organization.Author.ID, organization.LastEditor.ID)
+ if err != nil {
+ return entity.Organization{}, err
+ }
+
+ ID, err := result.LastInsertId()
+ if err != nil {
+ return entity.Organization{}, err
+ }
+
+ organization.ID = ID
+ if len(organization.Addresses) > 0 {
+ for i, a := range organization.Addresses {
+ a.Organization = &organization
+ address, err := c.SetOrganizationAddress(a)
+ if err != nil {
+ fmt.Println("Error to save addresses")
+ return entity.Organization{}, err
+ }
+ organization.Addresses[i] = address
+ }
+ }
+
+ if len(organization.Contacts) > 0 {
+ for i, ct := range organization.Contacts {
+ ct.Organization = &organization
+ contact, err := c.SetOrganizationContact(ct)
+ if err != nil {
+ fmt.Println("Error to save contacts")
+ return entity.Organization{}, err
+ }
+ organization.Contacts[i] = contact
+ }
+ }
+
+ return organization, nil
+}
diff --git a/data/datamysql/profile.go b/data/datamysql/profile.go
new file mode 100644
index 0000000..5fe6df7
--- /dev/null
+++ b/data/datamysql/profile.go
@@ -0,0 +1,77 @@
+package datamysql
+
+import (
+ "database/sql"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+// rideRepo maps methods to database
+type profileRepo struct {
+ conn executor
+}
+
+func newProfileRepo(conn executor) *profileRepo {
+ return &profileRepo{
+ conn: conn,
+ }
+}
+
+func (c *profileRepo) getQuery() string {
+ const (
+ query = `SELECT
+ a.profile_id,
+ a.name,
+ a.key,
+ a.description,
+ a.create_time,
+ a.update_time,
+ (a.active = b'1') active,
+ (a.visible = b'1') visible
+ FROM
+ tab_profile a `
+ )
+
+ return query
+}
+
+// parseSet parses a result set result to an entity array
+func (c *profileRepo) parseSet(rows *sql.Rows, err error) ([]entity.Profile, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.Profile, 0)
+ for rows.Next() {
+ entity, err := c.parseEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *profileRepo) parseEntity(row scanner) (retVal entity.Profile, err error) {
+ err = row.Scan(
+ &retVal.ID, &retVal.Name, &retVal.Key, &retVal.Description, &retVal.Created, &retVal.Updated, &retVal.Active, &retVal.Visible)
+
+ return retVal, errors.Wrap(err)
+}
+
+func (c *profileRepo) GetAll() ([]entity.Profile, error) {
+ return c.parseSet(c.conn.Query(c.getQuery()))
+}
+
+func (c *profileRepo) GetByKey(key string) (entity.Profile, error) {
+ return c.parseEntity(c.conn.QueryRow(c.getQuery()+"WHERE a.active = 1 AND a.key = ?", key))
+}
+
+func (c *profileRepo) GetVisibles(visible bool) ([]entity.Profile, error) {
+ return c.parseSet(c.conn.Query(c.getQuery()+"WHERE a.active = 1 AND a.visible = ?", visible))
+}
+
+func (c *profileRepo) GetByOrganizationType(organizationTypeID int64) ([]entity.Profile, error) {
+ return c.parseSet(c.conn.Query(c.getQuery()+" INNER JOIN tab_organization_type_profile b ON a.profile_id = b.profile_id WHERE a.active = 1 AND a.visible = 1 AND b.organization_type_id = ?", organizationTypeID))
+}
diff --git a/data/datamysql/provider.go b/data/datamysql/provider.go
new file mode 100644
index 0000000..426c434
--- /dev/null
+++ b/data/datamysql/provider.go
@@ -0,0 +1,421 @@
+package datamysql
+
+import (
+ "database/sql"
+ "fmt"
+ "strconv"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/go-sql-driver/mysql"
+ uuid "github.com/satori/go.uuid"
+)
+
+// rideRepo maps methods to database
+type providerRepo struct {
+ conn executor
+}
+
+func newProviderRepo(conn executor) *providerRepo {
+ return &providerRepo{
+ conn: conn,
+ }
+}
+
+func (c *providerRepo) getProfileQuery(user entity.User) (query string, where string, err error) {
+ if len(user.Profiles) > 0 {
+ for _, p := range user.Profiles {
+ switch p.Key {
+ case "AD", "BCBSIAD", "BDCAD", "PLANAD":
+ return
+ case "SP", "SPT":
+ switch p.Organization.Type.Key {
+ case "techsupport", "bcbsi", "bcbsa", "plan":
+ return
+ case "provider":
+ query = ` INNER JOIN viw_organization_provider c
+ ON a.provider_id = c.provider_id `
+ where = fmt.Sprintf(` AND (c.organization_uuid = '%s' OR c.parent_organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
+ return
+ }
+ }
+ }
+
+ if query == "" && where == "" {
+ return "", "", fmt.Errorf("Invalid Query")
+ } else {
+ return
+ }
+ } else {
+ return "", "", fmt.Errorf("User has no profile to search")
+ }
+}
+
+func (c *providerRepo) getSelectQueryBaseKey() string {
+ return `SELECT
+ a.provider_key_id,
+ a.provider_id,
+ a.internal_id,
+ a.internal_id_suffix,
+ a.location_seq_num,
+ a.plan_code,
+ a.product_id,
+ a.treatment_category_code,
+ a.active,
+ a.enabled,
+ a.create_at,
+ a.update_at,
+ a.created_user
+ FROM tab_provider_key a `
+}
+
+func (c *providerRepo) getSelectQueryBase() string {
+ return `SELECT DISTINCT
+ a.provider_id,
+ a.provider_uuid,
+ a.provider_internal_id,
+ a.provider_internal_id_suffix,
+ a.provider_muk_id,
+ a.organization_name,
+ a.gender,
+ a.accept_new_patients,
+ a.provider_name,
+ a.first_name,
+ a.last_name,
+ a.middle_name,
+ a.provider_title,
+ a.street_name1,
+ a.street_name2,
+ a.city_name,
+ a.state,
+ a.zipcode,
+ a.country,
+ a.latitude,
+ a.longitude,
+ a.phone_number,
+ a.create_at,
+ a.update_at,
+ a.active,
+ a.enabled,
+ a.created_user,
+ (3959 * acos (
+ cos ( radians(?) )
+ * cos( radians( a.latitude ) )
+ * cos( radians( a.longitude ) - radians(?) )
+ + sin ( radians(?) )
+ * sin( radians( a.latitude ) )
+ )) AS distance_in_miles
+ FROM
+ tab_provider a
+ INNER JOIN tab_provider_key b
+ ON a.provider_id = b.provider_id `
+}
+
+func (c *providerRepo) GetAll(user entity.User) ([]entity.Provider, error) {
+ lat := 41.886406
+ long := -87.624225
+
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return nil, err
+ }
+
+ query = c.getSelectQueryBase() + query + " WHERE 1 = 1 " + where
+
+ providers, err := c.parseSet(c.conn.Query(query, lat, long, lat))
+ if err != nil {
+ return nil, err
+ }
+
+ return c.getKeys("", "", providers)
+}
+
+func (c *providerRepo) GetByMukID(mukID string, user entity.User) (entity.Provider, error) {
+ lat := 41.886406
+ long := -87.624225
+
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return entity.Provider{}, err
+ }
+
+ query = c.getSelectQueryBase() + query + " WHERE a.provider_muk_id = ? " + where
+
+ return c.parseEntity(c.conn.QueryRow(query, lat, long, lat, mukID))
+}
+
+func (c *providerRepo) Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user entity.User) ([]entity.Provider, error) {
+ filter := " WHERE 1 = 1 "
+ params := make([]interface{}, 0)
+
+ if lat == 0 && long == 0 {
+ lat = 41.886406
+ long = -87.624225
+ }
+ params = append(params, lat, long, lat)
+
+ if query != "" && (mukID == "" && internalID == "") {
+ filter += " AND (a.provider_name LIKE ? OR a.street_name1 LIKE ? OR a.street_name2 LIKE ? OR a.zipcode LIKE ?) "
+ // MATCH(a.provider_internal_id, a.provider_internal_id_suffix, a.provider_muk_id, a.provider_name, a.street_name1, a.street_name2, a.city_name, a.state, a.zipcode, a.country, a.phone_number) AGAINST (?)
+
+ query = "%" + query + "%"
+ params = append(params, query, query, query, query)
+ }
+
+ if planCode != "" {
+ filter += " AND b.plan_code = ? "
+ params = append(params, planCode)
+ }
+
+ if productID != "" {
+ filter += " AND b.product_id = ? "
+ params = append(params, productID)
+ }
+
+ if mukID != "" {
+ filter += " AND a.provider_muk_id = ? "
+ params = append(params, mukID)
+ }
+
+ if internalID != "" {
+ filter += " AND a.provider_internal_id = ? "
+ params = append(params, internalID)
+ }
+
+ final := " HAVING distance_in_miles < ? "
+ params = append(params, distance)
+
+ if sort == "name" {
+ final += " ORDER BY a.provider_name ASC "
+ } else if sort == "distance" {
+ final += " ORDER BY distance_in_miles ASC "
+ }
+
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return nil, err
+ }
+
+ query = c.getSelectQueryBase() + query + filter + where + final
+
+ providers, err := c.parseSet(c.conn.Query(query, params...))
+ if err != nil {
+ return nil, err
+ }
+ if len(providers) > 0 {
+ return c.getKeys(planCode, productID, providers)
+ } else {
+ return providers, nil
+ }
+}
+
+func (c *providerRepo) getKeys(planCode string, productID string, providers []entity.Provider) ([]entity.Provider, error) {
+ var params []interface{}
+ var queryParams = " WHERE a.provider_id IN ("
+ for _, p := range providers {
+ queryParams += "?,"
+ params = append(params, p.ProviderID)
+ }
+ queryParams = queryParams[0 : len(queryParams)-1]
+ queryParams += ") "
+
+ if planCode != "" {
+ queryParams += " AND a.plan_code = ? "
+ params = append(params, planCode)
+ }
+
+ if productID != "" {
+ queryParams += " AND a.product_id = ? "
+ params = append(params, productID)
+ }
+
+ keys, err := c.parseKeySet(c.conn.Query(c.getSelectQueryBaseKey()+queryParams, params...))
+ if err != nil {
+ return nil, err
+ }
+ sortedResults := make(map[string][]entity.ProviderKey)
+ for _, k := range keys {
+ sortedKey := fmt.Sprintf("provider%v", k.Provider.ProviderID)
+ sortedResults[sortedKey] = append(sortedResults[sortedKey], k)
+ }
+
+ for i := range providers {
+ sortedKey := fmt.Sprintf("provider%v", providers[i].ProviderID)
+ providers[i].Keys = sortedResults[sortedKey]
+ }
+
+ return providers, nil
+}
+
+// parseSet parses a result set result to an entity array
+func (c *providerRepo) parseKeySet(rows *sql.Rows, err error) ([]entity.ProviderKey, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.ProviderKey, 0)
+ for rows.Next() {
+ entity, err := c.parseKeyEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *providerRepo) parseKeyEntity(row scanner) (retVal entity.ProviderKey, err error) {
+ err = row.Scan(
+ &retVal.ProviderKeyID, &retVal.Provider.ProviderID, &retVal.InternalID, &retVal.InternalSuffixID, &retVal.LocationSeqNumber, &retVal.PlanCode, &retVal.ProductID, &retVal.TreatmentCategoryCode, &retVal.Active, &retVal.Enabled, &retVal.CreateDate, &retVal.UpdateDate, &retVal.CreatedUser.ID)
+
+ return retVal, errors.Wrap(err)
+}
+
+// parseSet parses a result set result to an entity array
+func (c *providerRepo) parseSet(rows *sql.Rows, err error) ([]entity.Provider, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.Provider, 0)
+ for rows.Next() {
+ entity, err := c.parseEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *providerRepo) parseEntity(row scanner) (retVal entity.Provider, err error) {
+ err = row.Scan(
+ &retVal.ProviderID, &retVal.ProviderUUID, &retVal.InternalID, &retVal.InternalSuffixID, &retVal.MukID, &retVal.OrganizatioName, &retVal.Gender, &retVal.AcceptNewPatients, &retVal.Name, &retVal.FirstName, &retVal.LastName, &retVal.MiddleName, &retVal.Title, &retVal.Address.StreetAddress1, &retVal.Address.StreetAddress2, &retVal.Address.CityName, &retVal.Address.State, &retVal.Address.ZipCode, &retVal.Address.Country, &retVal.Address.Latitude, &retVal.Address.Longitude, &retVal.Address.PhoneNumber, &retVal.CreateDate, &retVal.UpdateDate, &retVal.Active, &retVal.Enabled, &retVal.CreatedUser.ID, &retVal.Distance)
+
+ return retVal, errors.Wrap(err)
+}
+
+func (c *providerRepo) Save(providers []entity.ProviderResponse, user entity.User) ([]entity.Provider, error) {
+ var savedProviders = make([]entity.Provider, 0)
+ for _, p := range providers {
+ provider, err := c.saveProvider(p, user)
+ if err != nil {
+ if driverErr, ok := err.(*mysql.MySQLError); ok {
+ if driverErr.Number != 1062 {
+ return nil, err
+ }
+ } else {
+ return nil, err
+ }
+ } else {
+ savedProviders = append(savedProviders, provider)
+ }
+ }
+
+ return savedProviders, nil
+}
+
+func (c *providerRepo) saveProvider(provider entity.ProviderResponse, user entity.User) (entity.Provider, error) {
+ const (
+ query = `INSERT INTO tab_provider(provider_uuid,provider_internal_id,provider_internal_id_suffix,provider_muk_id,organization_name,gender,accept_new_patients,provider_name,first_name,last_name,middle_name,provider_title,street_name1,street_name2,city_name,state,zipcode,country,latitude,longitude,phone_number,created_user)
+ VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);`
+ )
+
+ UUID, _ := uuid.NewV4()
+ lat, _ := strconv.ParseFloat(provider.Latitude, 64)
+ long, _ := strconv.ParseFloat(provider.Longitude, 64)
+
+ p := entity.Provider{
+ ProviderUUID: UUID.String(),
+ InternalID: provider.FivePartKeyGroups[0].ProviderNum,
+ InternalSuffixID: provider.FivePartKeyGroups[0].ProviderNumSuffix,
+ MukID: provider.MukID,
+ OrganizatioName: provider.OrgName,
+ Gender: provider.Gender,
+ AcceptNewPatients: provider.AcceptNewPatients,
+ Name: provider.ProviderName,
+ FirstName: provider.FirstName,
+ MiddleName: provider.MiddleName,
+ LastName: provider.LastName,
+ Title: provider.ProviderTitle,
+ Address: entity.ProviderAddress{
+ StreetAddress1: provider.StreetName1,
+ StreetAddress2: provider.StreetName2,
+ CityName: provider.CityName,
+ State: provider.State,
+ ZipCode: provider.ZipCode,
+ Country: provider.Country,
+ Latitude: lat,
+ Longitude: long,
+ PhoneNumber: provider.PhoneNumber,
+ },
+ CreateDate: time.Now(),
+ UpdateDate: time.Now(),
+ Active: true,
+ Enabled: true,
+ }
+
+ result, err := c.conn.Exec(query, p.ProviderUUID, p.InternalID, p.InternalSuffixID, p.MukID, p.OrganizatioName, p.Gender, p.AcceptNewPatients, p.Name, p.FirstName, p.LastName, p.MiddleName, p.Title, p.Address.StreetAddress1, p.Address.StreetAddress2, p.Address.CityName, p.Address.State, p.Address.ZipCode, p.Address.Country, p.Address.Latitude, p.Address.Longitude, p.Address.PhoneNumber, 1)
+ if err != nil {
+ if driverErr, ok := err.(*mysql.MySQLError); ok {
+ if driverErr.Number != 1062 {
+ return entity.Provider{}, err
+ } else {
+ tempProvider, err := c.GetByMukID(p.MukID, user)
+ if err != nil {
+ return entity.Provider{}, err
+ }
+ p.ProviderID = tempProvider.ProviderID
+ }
+ }
+ } else {
+ p.ProviderID, err = result.LastInsertId()
+ if err != nil {
+ return entity.Provider{}, err
+ }
+ }
+
+ var providerKeys []entity.ProviderKey
+ for _, fk := range provider.FivePartKeyGroups {
+ key, err := c.saveKeys(p.ProviderID, fk)
+ if err != nil {
+ return p, err
+ }
+ providerKeys = append(providerKeys, key)
+ }
+ p.Keys = providerKeys
+
+ return p, nil
+}
+
+func (c *providerRepo) saveKeys(ProviderID int64, fk entity.PartKeyGroup) (entity.ProviderKey, error) {
+ const (
+ query = `INSERT INTO tab_provider_key (provider_id, internal_id, internal_id_suffix, location_seq_num, plan_code, product_id, treatment_category_code, created_user)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE provider_id = ?, internal_id = ?, internal_id_suffix = ?, location_seq_num = ?, plan_code = ?, product_id = ?, treatment_category_code = ?, created_user = ?;`
+ )
+
+ key := entity.ProviderKey{
+ InternalID: fk.ProviderNum,
+ InternalSuffixID: fk.ProviderNumSuffix,
+ TreatmentCategoryCode: fk.TreatmentCategoryCode,
+ ProductID: fk.ProductID,
+ PlanCode: fk.PlanCode,
+ LocationSeqNumber: fk.LocationSeqNum,
+ Provider: entity.Provider{
+ ProviderID: ProviderID,
+ },
+ }
+
+ result, err := c.conn.Exec(query, key.Provider.ProviderID, key.InternalID, key.InternalSuffixID, key.LocationSeqNumber, key.PlanCode, key.ProductID, key.TreatmentCategoryCode, 1, key.Provider.ProviderID, key.InternalID, key.InternalSuffixID, key.LocationSeqNumber, key.PlanCode, key.ProductID, key.TreatmentCategoryCode, 1)
+ if err != nil {
+ return key, err
+ }
+
+ key.ProviderKeyID, err = result.LastInsertId()
+ if err != nil {
+ return key, err
+ }
+
+ return key, nil
+}
diff --git a/data/datamysql/ride.go b/data/datamysql/ride.go
new file mode 100644
index 0000000..74da273
--- /dev/null
+++ b/data/datamysql/ride.go
@@ -0,0 +1,826 @@
+package datamysql
+
+import (
+ "database/sql"
+ "fmt"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/go-sql-driver/mysql"
+ uuid "github.com/satori/go.uuid"
+)
+
+// rideRepo maps methods to database
+type rideRepo struct {
+ conn executor
+}
+
+func newRideRepo(conn executor) *rideRepo {
+ return &rideRepo{
+ conn: conn,
+ }
+}
+
+func (c *rideRepo) getQuery() string {
+ const query = `SELECT
+ a.ride_id,
+ a.ride_uuid,
+ b.user_id,
+ b.user_uuid,
+ b.name,
+ b.member,
+ c.ride_status_id,
+ c.ride_status,
+ c.key ride_status_key,
+ d.ride_type_id,
+ d.value ride_type,
+ d.key ride_type_key,
+ a.notes,
+ e.first_name,
+ e.last_name,
+ e.image_url,
+ e.phone_number,
+ e.internal_user_id,
+ IFNULL(f.name, '') driver_name,
+ IFNULL(f.phone_number, '') driver_phone_number,
+ IFNULL(f.image_url, '') driver_image_url,
+ IFNULL(f.rating, '') driver_rating,
+ IFNULL(g.color, '') vehicle_color,
+ IFNULL(g.image_url, '') vehicle_image_url,
+ IFNULL(g.license_plate, '') vehicle_license_plate,
+ IFNULL(g.license_plate_state, '') vehicle_license_state,
+ IFNULL(g.make, '') vehicle_make,
+ IFNULL(g.model, '') vehicle_model,
+ IFNULL(g.year, 0) vehicle_year,
+ h.origin_name,
+ h.origin_address,
+ h.origin_lat,
+ h.origin_lng,
+ h.destination_name,
+ h.destination_address,
+ h.destination_lat,
+ h.destination_lng,
+ IFNULL(h.route_kml, '') route_kml,
+ IFNULL(h.distance, 0) distance,
+ IFNULL(h.duration, 0) duration,
+ IFNULL(h.eta, 0) eta,
+ a.pickup_time,
+ a.visit_date,
+ a.visit_time,
+ a.ride_internal_id,
+ a.visit_id,
+ i.visit_uuid,
+ IFNULL(i.pickup_id, '') visit_pickup_id,
+ IFNULL(i.pickup_address_id, 0) pickup_address_id,
+ IFNULL(i.address_id, 0) address_id,
+ IFNULL(i.provider_id, 0) provider_id,
+ IFNULL(o.provider_uuid, '') provider_uuid,
+ IFNULL(o.provider_internal_id, '') provider_internal_id,
+ IFNULL(o.provider_muk_id, '') provider_muk_id,
+ IFNULL(o.provider_name, '') provider_name,
+ -- i.pickup_name visit_pickup_name,
+ -- i.pickup_address visit_pickup_address,
+ -- i.pickup_lat visit_pickup_lat,
+ -- i.pickup_lng visit_pickup_lng,
+ -- IFNULL(i.destination_id, '') visit_destination_id,
+ -- i.destination_name visit_destination_name,
+ -- i.destination_address visit_destination_address,
+ -- i.destination_lat visit_destination_lat,
+ -- i.destination_lng visit_destination_lng,
+ IFNULL(i.visit_external_id, '') visit_external_id,
+ i.created_user_id,
+ j.user_uuid created_user_uuid,
+ j.name created_name,
+ IFNULL(k.phone_number, '') created_user_phone_number,
+ IFNULL(k.email, '') created_user_email,
+ IFNULL(l.phone_number, '') user_phone_number,
+ IFNULL(l.email, '') user_email,
+ a.create_date,
+ a.update_date,
+ m.trip_type_id,
+ m.trip_type_key,
+ m.trip_type,
+ n.trip_type_id visit_trip_type_id,
+ n.trip_type_key visit_trip_type_key,
+ n.trip_type visit_trip_type_key,
+ i.return_date
+ FROM tab_ride a
+ INNER JOIN tab_user b
+ ON a.user_id = b.user_id
+ INNER JOIN tab_ride_status c
+ ON c.ride_status_id = a.ride_status_id
+ INNER JOIN tab_ride_type d
+ ON d.ride_type_id = a.ride_type_id
+ INNER JOIN tab_ride_passenger e
+ ON e.ride_id = a.ride_id
+ LEFT JOIN tab_ride_driver f
+ ON f.ride_id = a.ride_id
+ LEFT JOIN tab_ride_vehicle g
+ ON g.ride_id = a.ride_id
+ INNER JOIN tab_ride_route h
+ ON h.ride_id = a.ride_id
+ INNER JOIN tab_visit i
+ ON i.visit_id = a.visit_id
+ INNER JOIN tab_user j
+ ON j.user_id = i.created_user_id
+ INNER JOIN tab_login k
+ ON k.user_id = j.user_id
+ INNER JOIN tab_login l
+ ON l.user_id = a.user_id
+ INNER JOIN tab_trip_type m
+ ON m.trip_type_id = a.trip_type_id
+ INNER JOIN tab_trip_type n
+ ON n.trip_type_id = i.trip_type_id
+ INNER JOIN tab_provider o
+ ON i.provider_id = o.provider_id `
+
+ return query
+}
+
+func (c *rideRepo) getProfileQuery(user entity.User) (query string, where string, err error) {
+ if len(user.Profiles) > 0 {
+ for _, p := range user.Profiles {
+ switch p.Key {
+ case "AD", "BCBSIAD", "BDCAD", "PLANAD":
+ return
+ case "SP", "SPT":
+ switch p.Organization.Type.Key {
+ case "techsupport", "bcbsi", "bcbsa", "plan":
+ return
+ case "provider":
+ query = `INNER JOIN viw_visit_provider o ON a.ride_id = o.ride_id`
+ where = fmt.Sprintf(` AND (o.organization_uuid = '%s' OR o.parent_organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
+ return
+ }
+ }
+ }
+
+ if query == "" && where == "" {
+ return "", "", fmt.Errorf("Invalid Query")
+ } else {
+ return
+ }
+ } else {
+ return "", "", fmt.Errorf("User has no profile to search")
+ }
+}
+
+func (c *rideRepo) Update(hook entity.WebhookResponse, user entity.User) (retVal entity.Ride, err error) {
+ oldRide, err := c.GetByUUID(hook.Ride.UUID, user)
+ if err != nil {
+ return retVal, err
+ }
+
+ retVal, err = c.updateHeader(hook.Ride)
+ if err != nil {
+ return retVal, err
+ }
+
+ retVal, err = c.updateLocation(hook.Ride)
+ if err != nil {
+ return retVal, err
+ }
+
+ // retVal, err = c.updatePassenger(hook.Ride)
+ // if err != nil {
+ // return retVal, err
+ // }
+
+ if oldRide.Driver.Name != "" {
+ retVal, err = c.updateDriver(hook.Ride)
+ } else {
+ retVal, err = c.saveDriver(hook.Ride)
+ }
+ if err != nil {
+ return retVal, err
+ }
+
+ if oldRide.Vehicle.LicensePlate != "" {
+ retVal, err = c.updateVehicle(hook.Ride)
+ } else {
+ retVal, err = c.saveVehicle(hook.Ride)
+ }
+ if err != nil {
+ return retVal, err
+ }
+
+ go func() {
+ err := c.saveHistory(hook)
+ if err != nil {
+ fmt.Println("Error to save history: " + err.Error())
+ }
+ }()
+
+ return retVal, nil
+}
+
+func (c *rideRepo) updateVehicle(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ query = `UPDATE tab_ride_vehicle
+ SET
+ color = ?,
+ image_url = ?,
+ license_plate = ?,
+ license_plate_state = ?,
+ make = ?,
+ model = ?,
+ year = ?
+ WHERE ride_id = ?;`
+ )
+
+ retVal = ride
+ _, err = c.conn.Exec(query, ride.Vehicle.Color, ride.Vehicle.ImageURL, ride.Vehicle.LicensePlate, ride.Vehicle.LicensePlateState, ride.Vehicle.Make, ride.Vehicle.Model, ride.Vehicle.Year, ride.ID)
+ if err != nil {
+ return retVal, err
+ }
+
+ return retVal, nil
+}
+
+func (c *rideRepo) updateDriver(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ query = `UPDATE tab_ride_driver
+ SET
+ name = ?,
+ image_url = ?,
+ phone_number = ?,
+ rating = ?
+ WHERE ride_id = ?;`
+ )
+
+ retVal = ride
+ _, err = c.conn.Exec(query, ride.Driver.Name, ride.Driver.ImageURL, ride.Driver.PhoneNumber, ride.Driver.Rating, ride.ID)
+ if err != nil {
+ return retVal, err
+ }
+
+ return retVal, nil
+}
+
+func (c *rideRepo) updatePassenger(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ query = `UPDATE tab_ride_passenger
+ SET
+ first_name = ?,
+ last_name = ?,
+ image_url = ?,
+ phone_number = ?,
+ internal_user_id = ?
+ WHERE ride_id = ?;`
+ )
+
+ retVal = ride
+ _, err = c.conn.Exec(query, ride.Passenger.FirstName, ride.Passenger.LastName, ride.Passenger.ImageURL, ride.Passenger.PhoneNumber, ride.Passenger.InternalID, ride.ID)
+ if err != nil {
+ return retVal, err
+ }
+
+ return retVal, nil
+}
+
+func (c *rideRepo) updateLocation(ride entity.Ride) (retVal entity.Ride, err error) {
+ query := `UPDATE tab_ride_route
+ SET
+ origin_address = ?,
+ origin_lat = ?,
+ origin_lng = ?,
+ destination_address = ?,
+ destination_lat = ?,
+ destination_lng = ?,
+ route_kml = ?,
+ distance = ?,
+ duration = ?,
+ eta = ?`
+ where := ` WHERE ride_id = ?;`
+
+ retVal = ride
+ params := make([]interface{}, 0)
+ params = append(params, ride.Route.Origin.Address, ride.Route.Origin.Latitude, ride.Route.Origin.Longitude, ride.Route.Destination.Address, ride.Route.Destination.Latitude, ride.Route.Destination.Longitude, ride.Route.RouteKML, ride.Route.Distance, ride.Route.Duration, ride.Route.ETA)
+
+ if retVal.Route.Origin.Name != "" {
+ query += " , origin_name = ? "
+ params = append(params, ride.Route.Origin.Name)
+ }
+
+ if retVal.Route.Destination.Name != "" {
+ query += " , destination_name = ? "
+ params = append(params, ride.Route.Destination.Name)
+ }
+ params = append(params, ride.ID)
+
+ _, err = c.conn.Exec(query+where, params...)
+ if err != nil {
+ return retVal, err
+ }
+
+ return retVal, nil
+}
+
+func (c *rideRepo) updateHeader(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ statusQuery = "SELECT ride_status_id FROM tab_ride_status WHERE `key` = ?"
+ query = `UPDATE tab_ride
+ SET
+ ride_status_id = ?,
+ ride_type_id = ?,
+ ride_internal_id = ?,
+ request_date = ?,
+ request_ms = ?,
+ generate_date = ?,
+ generate_ms = ?,
+ route_kml = ?,
+ notes = ?,
+ primetime_percentage = ?,
+ pickup_time = ?,
+ visit_date = ?,
+ visit_time = ?,
+ visit_id = ?
+ WHERE ride_uuid = ?;`
+ )
+
+ row := c.conn.QueryRow(statusQuery, ride.Status.Key)
+ err = row.Scan(&ride.Status.ID)
+ if err != nil {
+ fmt.Println("Error to get status")
+ return retVal, err
+ }
+
+ retVal = ride
+ _, err = c.conn.Exec(query, ride.Status.ID, ride.Type.ID, ride.InternalID, ride.RequestDate, ride.RequestMiliseconds, ride.GenerateDate, ride.GenerateMiliseconds, ride.Route.RouteKML, ride.Note, ride.PrimetimePercentage, ride.PickupTime, ride.VisitDate, ride.VisitTime, ride.Visit.ID, ride.UUID)
+ if err != nil {
+ return retVal, err
+ }
+
+ return ride, nil
+}
+
+func (c *rideRepo) Save(ride entity.Ride) (retVal entity.Ride, err error) {
+ retVal, err = c.saveHeader(ride)
+ if err != nil {
+ fmt.Println("Error to save header")
+ return retVal, err
+ }
+
+ retVal, err = c.saveLocation(retVal)
+ if err != nil {
+ fmt.Println("Error to save location")
+ return retVal, err
+ }
+
+ retVal, err = c.savePassenger(retVal)
+ if err != nil {
+ fmt.Println("Error to save passenger")
+ return retVal, err
+ }
+
+ retVal, err = c.saveDriver(retVal)
+ if err != nil {
+ fmt.Println("Error to save driver")
+ return retVal, err
+ }
+
+ retVal, err = c.saveVehicle(retVal)
+ if err != nil {
+ fmt.Println("Error to save vehicle")
+ return retVal, err
+ }
+
+ go func() {
+ hook := entity.WebhookResponse{
+ Ride: retVal,
+ }
+ err = c.saveHistory(hook)
+ if err != nil {
+ fmt.Println("Error to save history: ", err.Error())
+ }
+ }()
+
+ return retVal, err
+}
+
+func (c *rideRepo) saveHistory(hook entity.WebhookResponse) error {
+ rideHistoryID, err := c.saveHistoryHeader(hook)
+ if err != nil {
+ fmt.Println("Error to save header history")
+ return err
+ }
+
+ if err = c.saveLocationHistory(rideHistoryID, hook.Ride.Route); err != nil {
+ fmt.Println("Error to save location history")
+ return err
+ }
+
+ if err = c.savePassengerHistory(rideHistoryID, hook.Ride.Passenger); err != nil {
+ fmt.Println("Error to save passenger history")
+ return err
+ }
+
+ if err = c.saveDriverHistory(rideHistoryID, hook.Ride.Driver); err != nil {
+ fmt.Println("Error to save driver history")
+ return err
+ }
+
+ if err = c.saveVehicleHistory(rideHistoryID, hook.Ride.Vehicle); err != nil {
+ fmt.Println("Error to save vehicle history")
+ return err
+ }
+
+ return nil
+}
+
+func (c *rideRepo) saveVehicleHistory(rideHistoryID int64, vehicle entity.RideVehicle) error {
+ const (
+ query = "INSERT INTO tab_ride_vehicle_history(ride_history_id,color,image_url,license_plate,license_plate_state,make,model,`year`) VALUES(?,?,?,?,?,?,?,?);"
+ )
+
+ if vehicle.Make != "" && vehicle.Model != "" && vehicle.Color != "" && vehicle.Year > 0 {
+ _, err := c.conn.Exec(query, rideHistoryID, vehicle.Color, vehicle.ImageURL, vehicle.LicensePlate, vehicle.LicensePlateState, vehicle.Make, vehicle.Model, vehicle.Year)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (c *rideRepo) saveDriverHistory(rideHistoryID int64, driver entity.RideDriver) error {
+ const (
+ query = "INSERT INTO tab_ride_driver_history(ride_history_id,name,image_url,phone_number,rating) VALUES(?,?,?,?,?);"
+ )
+
+ if driver.Name != "" && driver.PhoneNumber != "" {
+ _, err := c.conn.Exec(query, rideHistoryID, driver.Name, driver.ImageURL, driver.PhoneNumber, driver.Rating)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (c *rideRepo) savePassengerHistory(rideHistoryID int64, passenger entity.RidePassenger) error {
+ const (
+ query = "INSERT INTO tab_ride_passenger_history(ride_history_id,first_name,last_name,image_url,phone_number,internal_user_id) VALUES(?,?,?,?,?,?)"
+ )
+
+ _, err := c.conn.Exec(query, rideHistoryID, passenger.FirstName, passenger.LastName, "", passenger.PhoneNumber, passenger.InternalID)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (c *rideRepo) saveLocationHistory(rideHistoryID int64, route entity.RideRoute) error {
+ const (
+ query = `INSERT INTO tab_ride_route_history(ride_history_id,origin_name,origin_address,origin_lat,origin_lng,destination_name,destination_address,destination_lat,destination_lng,route_kml,distance,duration,eta)
+ VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?);`
+ )
+
+ if route.Origin.Latitude != 0 && route.Origin.Longitude != 0 && route.Destination.Latitude != 0 && route.Destination.Longitude != 0 {
+ _, err := c.conn.Exec(query, rideHistoryID, route.Origin.Name, route.Origin.Address, route.Origin.Latitude, route.Origin.Longitude, route.Destination.Name, route.Destination.Address, route.Destination.Latitude, route.Destination.Longitude, route.RouteKML, route.Distance, route.Duration, route.ETA)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (c *rideRepo) saveHistoryHeader(hook entity.WebhookResponse) (int64, error) {
+ const (
+ query = `INSERT INTO tab_ride_history(ride_history_uuid,ride_id,event_id,href,occurred_at,event_type,ride_internal_id,ride_status_id,ride_type_id,request_date,request_ms,generate_date,generate_ms,route_kml,notes, primetime_percentage, pickup_time, visit_date, visit_time, visit_id)
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);`
+ )
+
+ UUID, _ := uuid.NewV4()
+ sUUID := UUID.String()
+
+ if hook.OccurredAt.IsZero() {
+ hook.OccurredAt = time.Now()
+ }
+
+ results, err := c.conn.Exec(query, sUUID, hook.Ride.ID, hook.EventID, hook.HREF, hook.OccurredAt, hook.EventType, hook.Ride.InternalID, hook.Ride.Status.ID, hook.Ride.Type.ID, hook.Ride.RequestDate, hook.Ride.RequestMiliseconds, hook.Ride.GenerateDate, hook.Ride.GenerateMiliseconds, hook.Ride.Route.RouteKML, hook.Ride.Note, hook.Ride.PrimetimePercentage, hook.Ride.PickupTime, hook.Ride.VisitDate, hook.Ride.VisitTime, hook.Ride.Visit.ID)
+ if err != nil {
+ return 0, err
+ }
+
+ return results.LastInsertId()
+}
+
+func (c *rideRepo) saveHeader(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ dataQuery = `SELECT
+ a.user_id user_id,
+ a.name,
+ a.member,
+ b.ride_status_id,
+ b.ride_status,
+ c.ride_type_id,
+ c.value ride_type,
+ d.user_id created_user_id,
+ d.name created_name,
+ IFNULL(d.member, '') created_member,
+ e.trip_type_id,
+ e.trip_type_key,
+ e.trip_type
+ FROM tab_user a,
+ tab_ride_status b,
+ tab_ride_type c,
+ tab_user d,
+ tab_trip_type e
+ WHERE
+ a.user_uuid = ?
+ AND b.key = ?
+ AND c.key = ?
+ AND d.user_uuid = ?
+ AND e.trip_type_key = ?;`
+
+ query = `INSERT INTO tab_ride(ride_uuid, user_id, ride_status_id, ride_type_id, ride_internal_id, request_date, request_ms, generate_date, generate_ms, notes, primetime_percentage, pickup_time, visit_date, visit_time, visit_id, created_user_id, trip_type_id)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`
+ )
+
+ retVal = ride
+ UUID, _ := uuid.NewV4()
+ retVal.UUID = UUID.String()
+
+ if retVal.Status.Key == "" {
+ retVal.Status.Key = "accepted"
+ }
+
+ if retVal.Type.Key == "" {
+ retVal.Type.Key = "lyft"
+ }
+
+ row := c.conn.QueryRow(dataQuery, retVal.User.UUID, retVal.Status.Key, retVal.Type.Key, retVal.CreatedUser.UUID, retVal.TripType.Key)
+ if err = row.Scan(&retVal.User.ID, &retVal.User.Name, &retVal.User.Member, &retVal.Status.ID, &retVal.Status.Value, &retVal.Type.ID, &retVal.Type.Value, &retVal.CreatedUser.ID, &retVal.CreatedUser.Name, &retVal.CreatedUser.Member, &retVal.TripType.ID, &retVal.TripType.Key, &retVal.TripType.Value); err != nil {
+ fmt.Println("Error to get base data: ", err.Error())
+ return retVal, err
+ }
+
+ results, err := c.conn.Exec(query, retVal.UUID, retVal.User.ID, retVal.Status.ID, retVal.Type.ID, retVal.InternalID, retVal.RequestDate, retVal.RequestMiliseconds, retVal.GenerateDate, retVal.GenerateMiliseconds, retVal.Note, retVal.PrimetimePercentage, retVal.PickupTime, retVal.VisitDate, retVal.VisitTime, retVal.Visit.ID, retVal.CreatedUser.ID, retVal.TripType.ID)
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return retVal, err
+ }
+
+ var ID int64
+ ID, err = results.LastInsertId()
+ if err != nil {
+ fmt.Println("Error Getting the ID: ", err.Error())
+ return retVal, err
+ }
+
+ retVal.ID = ID
+ return retVal, nil
+}
+
+func (c *rideRepo) saveLocation(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ query = `INSERT INTO tab_ride_route(ride_id,origin_name,origin_address,origin_lat,origin_lng,destination_name,destination_address,destination_lat,destination_lng,route_kml,distance,duration,eta)
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?);`
+ )
+
+ retVal = ride
+ results, err := c.conn.Exec(query, retVal.ID, retVal.Route.Origin.Name, retVal.Route.Origin.Address, retVal.Route.Origin.Latitude, retVal.Route.Origin.Longitude, retVal.Route.Destination.Name, retVal.Route.Destination.Address, retVal.Route.Destination.Latitude, retVal.Route.Destination.Longitude, retVal.Route.RouteKML, retVal.Route.Distance, retVal.Route.Duration, retVal.Route.ETA)
+ if err != nil {
+ return retVal, err
+ }
+
+ var ID int64
+ ID, err = results.LastInsertId()
+ if err != nil {
+ fmt.Println("Error Getting the ID: ", err.Error())
+ return retVal, err
+ }
+
+ retVal.Route.ID = ID
+ return retVal, nil
+}
+
+func (c *rideRepo) savePassenger(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ query = `INSERT INTO tab_ride_passenger(ride_id,first_name,last_name,image_url,phone_number,internal_user_id)
+ VALUES(?,?,?,?,?,?);`
+ )
+
+ retVal = ride
+ results, err := c.conn.Exec(query, retVal.ID, ride.Passenger.FirstName, ride.Passenger.LastName, ride.Passenger.ImageURL, ride.Passenger.PhoneNumber, ride.Passenger.InternalID)
+ if err != nil {
+ return retVal, err
+ }
+
+ var ID int64
+ ID, err = results.LastInsertId()
+ if err != nil {
+ fmt.Println("Error Getting the ID: ", err.Error())
+ return retVal, err
+ }
+
+ retVal.Passenger.ID = ID
+ return retVal, nil
+}
+
+func (c *rideRepo) saveDriver(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ query = "INSERT INTO tab_ride_driver(ride_id,`name`,image_url,phone_number,rating) VALUES(?,?,?,?,?);"
+ )
+
+ retVal = ride
+ if retVal.Driver.Name != "" && retVal.Driver.PhoneNumber != "" {
+ results, err := c.conn.Exec(query, retVal.ID, ride.Driver.Name, ride.Driver.ImageURL, ride.Driver.PhoneNumber, ride.Driver.Rating)
+ if err != nil {
+ return retVal, err
+ }
+
+ var ID int64
+ ID, err = results.LastInsertId()
+ if err != nil {
+ fmt.Println("Error Getting the ID: ", err.Error())
+ return retVal, err
+ }
+ retVal.Driver.ID = ID
+ }
+ return retVal, nil
+}
+
+func (c *rideRepo) saveVehicle(ride entity.Ride) (retVal entity.Ride, err error) {
+ const (
+ query = "INSERT INTO tab_ride_vehicle(ride_id,color,image_url,license_plate,license_plate_state,make,model,`year`) VALUES(?,?,?,?,?,?,?,?);"
+ )
+
+ retVal = ride
+ if retVal.Vehicle.Color != "" && retVal.Vehicle.LicensePlate != "" && retVal.Vehicle.Make != "" && retVal.Vehicle.Model != "" && retVal.Vehicle.Year > 0 {
+ results, err := c.conn.Exec(query, retVal.ID, ride.Vehicle.Color, ride.Vehicle.ImageURL, ride.Vehicle.LicensePlate, ride.Vehicle.LicensePlateState, ride.Vehicle.Make, ride.Vehicle.Model, ride.Vehicle.Year)
+ if err != nil {
+ return retVal, err
+ }
+
+ var ID int64
+ ID, err = results.LastInsertId()
+ if err != nil {
+ fmt.Println("Error Getting the ID: ", err.Error())
+ return retVal, err
+ }
+
+ retVal.Vehicle.ID = ID
+ }
+ return retVal, nil
+}
+
+func (c *rideRepo) GetByUUID(uuid string, user entity.User) (entity.Ride, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return entity.Ride{}, err
+ }
+
+ query = c.getQuery() + query + " WHERE a.ride_uuid = ? " + where
+ return c.parseEntity(c.conn.QueryRow(query, uuid))
+}
+
+func (c *rideRepo) GetByID(id int64, user entity.User) (entity.Ride, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return entity.Ride{}, err
+ }
+
+ query = c.getQuery() + query + " WHERE a.ride_id = ? " + where
+ return c.parseEntity(c.conn.QueryRow(query, id))
+}
+
+func (c *rideRepo) GetByUUIDAndUserUUID(UUID string, userUUID string) (entity.Ride, error) {
+ return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.ride_uuid = ? AND b.user_uuid = ?", UUID, userUUID))
+}
+
+func (c *rideRepo) GetLastRideByPhoneNumber(phoneNumber string) (entity.Ride, error) {
+ query := c.getQuery() + ` WHERE c.ride_status IN ('accepted', 'arrived', 'scheduled', 'pending')
+ AND l.phone_number = ?
+ ORDER BY a.create_date DESC
+ LIMIT 1;`
+
+ return c.parseEntity(c.conn.QueryRow(query, phoneNumber))
+}
+
+func (c *rideRepo) GetLastRideByDriversNumber(phoneNumber string) (entity.Ride, error) {
+ query := c.getQuery() + ` WHERE c.ride_status IN ('accepted', 'arrived', 'scheduled', 'pending')
+ AND IFNULL(f.phone_number, '') = ?
+ ORDER BY a.create_date DESC
+ LIMIT 1;`
+
+ return c.parseEntity(c.conn.QueryRow(query, phoneNumber))
+}
+
+func (c *rideRepo) GetByInternalID(internalID string) (entity.Ride, error) {
+ return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.ride_internal_id = ?", internalID))
+}
+
+func (c *rideRepo) GetByInternalPassengerID(internalPassengerID string) (entity.Ride, error) {
+ return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE e.internal_user_id = ?", internalPassengerID))
+}
+
+func (c *rideRepo) GetByUserID(userID int64, user entity.User) ([]entity.Ride, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return nil, err
+ }
+
+ query = c.getQuery() + query + " WHERE b.user_id = ? " + where
+
+ return c.parseSet(c.conn.Query(query, userID))
+}
+
+func (c *rideRepo) GetByUserUUID(userUUID string, user entity.User) ([]entity.Ride, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return nil, err
+ }
+
+ query = c.getQuery() + query + " WHERE b.user_uuid = ? " + where
+
+ return c.parseSet(c.conn.Query(query, userUUID))
+}
+
+func (c *rideRepo) GetByVisitUUID(visitUUID string, user entity.User) ([]entity.Ride, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return nil, err
+ }
+
+ query = c.getQuery() + query + " WHERE b.user_id = ? " + where
+
+ return c.parseSet(c.conn.Query(query, visitUUID))
+}
+
+func (c *rideRepo) GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user entity.User) (entity.Ride, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return entity.Ride{}, err
+ }
+
+ query = c.getQuery() + query + " WHERE i.visit_uuid = ? AND m.trip_type_key = ? " + where
+ return c.parseEntity(c.conn.QueryRow(query, visitUUID, tripTypeKey))
+}
+
+func (c *rideRepo) parseSet(rows *sql.Rows, err error) ([]entity.Ride, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.Ride, 0)
+ for rows.Next() {
+ entity, err := c.parseEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+func (c *rideRepo) parseEntity(row scanner) (r entity.Ride, err error) {
+ var returnDate mysql.NullTime
+
+ err = row.Scan(&r.ID, &r.UUID, &r.User.ID, &r.User.UUID, &r.User.Name, &r.User.Member, &r.Status.ID, &r.Status.Value, &r.Status.Key, &r.Type.ID, &r.Type.Value, &r.Type.Key, &r.Note, &r.Passenger.FirstName, &r.Passenger.LastName, &r.Passenger.ImageURL, &r.Passenger.PhoneNumber, &r.Passenger.InternalID, &r.Driver.Name, &r.Driver.PhoneNumber, &r.Driver.ImageURL, &r.Driver.Rating, &r.Vehicle.Color, &r.Vehicle.ImageURL, &r.Vehicle.LicensePlate, &r.Vehicle.LicensePlateState, &r.Vehicle.Make, &r.Vehicle.Model, &r.Vehicle.Year, &r.Route.Origin.Name, &r.Route.Origin.Address, &r.Route.Origin.Latitude, &r.Route.Origin.Longitude, &r.Route.Destination.Name, &r.Route.Destination.Address, &r.Route.Destination.Latitude, &r.Route.Destination.Longitude, &r.Route.RouteKML, &r.Route.Distance, &r.Route.Duration, &r.Route.ETA, &r.PickupTime, &r.VisitDate, &r.VisitTime, &r.InternalID, &r.Visit.ID, &r.Visit.UUID, &r.Visit.Pickup.ID, &r.Visit.PickupAddressID, &r.Visit.DestinationAddressID, &r.Visit.Provider.ProviderID, &r.Visit.Provider.ProviderUUID, &r.Visit.Provider.InternalID, &r.Visit.Provider.MukID, &r.Visit.Provider.Name, &r.Visit.ExternalID, &r.Visit.CreatedUser.ID, &r.Visit.CreatedUser.UUID, &r.Visit.CreatedUser.Name, &r.Visit.CreatedUser.PhoneNumber, &r.Visit.CreatedUser.Email, &r.User.PhoneNumber, &r.User.Email, &r.Created, &r.Updated, &r.TripType.ID, &r.TripType.Key, &r.TripType.Value, &r.Visit.TripType.ID, &r.Visit.TripType.Key, &r.Visit.TripType.Value, &returnDate)
+ if err != nil {
+ return r, errors.Wrap(err)
+ }
+
+ r.CreatedUser = r.Visit.CreatedUser
+ if returnDate.Valid {
+ r.Visit.ReturnDate = &returnDate.Time
+ }
+
+ return r, nil
+}
+
+func (c *rideRepo) UpdateStatus(rideUUID string, status string) error {
+ const (
+ statusQuery = "SELECT ride_status_id FROM tab_ride_status WHERE `key` = ?"
+ query = "UPDATE tab_ride SET ride_status_id = ? WHERE ride_uuid = ?"
+ )
+
+ var rideStatusID int64
+ row := c.conn.QueryRow(statusQuery, status)
+ err := row.Scan(&rideStatusID)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.conn.Exec(query, rideStatusID, rideUUID)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (c *rideRepo) GetAll(user entity.User) ([]entity.Ride, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return nil, err
+ }
+
+ query = c.getQuery() + query + " WHERE 1 = 1 AND b.active = 1 " + where
+
+ return c.parseSet(c.conn.Query(query))
+}
diff --git a/data/datamysql/transaction.go b/data/datamysql/transaction.go
new file mode 100644
index 0000000..7daae84
--- /dev/null
+++ b/data/datamysql/transaction.go
@@ -0,0 +1,87 @@
+package datamysql
+
+import (
+ "database/sql"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+type transaction struct {
+ tx *sql.Tx
+ users *userRepo
+ rides *rideRepo
+ visits *visitRepo
+ provider *providerRepo
+ notification *notificationRepo
+ profile *profileRepo
+ organization *organizationRepo
+}
+
+func newTransaction(tx *sql.Tx) *transaction {
+
+ t := new(transaction)
+
+ t.tx = tx
+ t.users = newUserRepo(tx)
+ t.rides = newRideRepo(tx)
+ t.visits = newVisitRepo(tx)
+ t.provider = newProviderRepo(tx)
+
+ return t
+}
+
+// Users returns the users set
+func (t transaction) Users() contract.UserRepo {
+ return t.users
+}
+
+// Rides returns the rides set
+func (t transaction) Rides() contract.RideRepo {
+ return t.rides
+}
+
+// Rides returns the rides set
+func (t transaction) Visits() contract.VisitRepo {
+ return t.visits
+}
+
+// Provider returns the rides set
+func (t transaction) Provider() contract.ProviderRepo {
+ return t.provider
+}
+
+// Provider returns the rides set
+func (t transaction) Profile() contract.ProfileRepo {
+ return t.profile
+}
+
+// Provider returns the rides set
+func (t transaction) Notification() contract.NotificationRepo {
+ return t.notification
+}
+
+// Provider returns the rides set
+func (t transaction) Organization() contract.OrganizationRepo {
+ return t.organization
+}
+
+func (t *transaction) Commit() error {
+
+ err := t.tx.Commit()
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
+
+func (t *transaction) Rollback() error {
+
+ err := t.tx.Rollback()
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
diff --git a/data/datamysql/user.go b/data/datamysql/user.go
new file mode 100644
index 0000000..2ae8be0
--- /dev/null
+++ b/data/datamysql/user.go
@@ -0,0 +1,825 @@
+package datamysql
+
+import (
+ "database/sql"
+ "fmt"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/go-sql-driver/mysql"
+ uuid "github.com/satori/go.uuid"
+)
+
+// userRepo maps methods to database
+type userRepo struct {
+ conn executor
+}
+
+func newUserRepo(conn executor) *userRepo {
+ return &userRepo{
+ conn: conn,
+ }
+}
+
+func (c *userRepo) GetByUUID(uuid string, profile string) (entity.User, error) {
+ params := make([]interface{}, 0)
+ params = append(params, uuid)
+ finalQuery := c.getQuery() + " AND a.user_uuid = ? "
+ if profile == "US" {
+ finalQuery += " AND e.key = ? "
+ params = append(params, profile)
+ }
+
+ user, err := c.parseSet(c.conn.Query(finalQuery, params...))
+ if err != nil {
+ return entity.User{}, err
+ }
+
+ if len(user) > 0 {
+ retVal := user[0]
+ retVal.Contacts, err = c.GetContacts(retVal.ID)
+ if err != nil {
+ return entity.User{}, err
+ }
+
+ retVal.Addresses = nil
+ retVal.Addresses, err = c.getAddressByUserID(retVal.ID)
+ if err != nil {
+ return entity.User{}, err
+ }
+ return retVal, nil
+ } else {
+ return entity.User{}, nil
+ }
+}
+
+func (c *userRepo) GetContacts(userID int64) ([]entity.ContactInfo, error) {
+ const (
+ query = `
+ SELECT
+ a.contact_id,
+ a.contact,
+ a.user_id,
+ b.contact_type_id,
+ b.key contact_type_key,
+ b.name contact_type_name
+ FROM tab_contact a
+ INNER JOIN tab_contact_type b
+ ON a.contact_type_id = b.contact_type_id
+ WHERE a.user_id = ?;
+ `
+ )
+
+ rows, err := c.conn.Query(query, userID)
+ if err != nil {
+ return nil, err
+ }
+
+ retVal := make([]entity.ContactInfo, 0)
+ for rows.Next() {
+ contact := entity.ContactInfo{}
+ err = rows.Scan(&contact.ID, &contact.Value, &contact.UserID, &contact.Type.ID, &contact.Type.Key, &contact.Type.Value)
+ if err != nil {
+ return nil, err
+ }
+ retVal = append(retVal, contact)
+ }
+
+ return retVal, nil
+}
+
+func (c *userRepo) GetUsersByProfile(profile string) ([]entity.User, error) {
+ query := c.getQuery()
+ if profile == "" {
+ query += "AND e.key <> 'US' "
+ return c.parseSet(c.conn.Query(query))
+ } else {
+ return c.parseSet(c.conn.Query(query+"AND e.key = ? AND a.active = 1 ", profile))
+ }
+}
+
+func (c *userRepo) parseSet(rows *sql.Rows, err error) ([]entity.User, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.User, 0)
+ var lastUser entity.User
+ for rows.Next() {
+ entity, err := c.parseEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ if entity.UUID == lastUser.UUID {
+ lastUser.Profiles = append(lastUser.Profiles, entity.Profiles...)
+ } else {
+ if lastUser.UUID != "" {
+ result = append(result, lastUser)
+ }
+ lastUser = entity
+ }
+ }
+ result = append(result, lastUser)
+
+ return result, nil
+}
+
+func (c *userRepo) GetContactType() (retVal []entity.ContactType, err error) {
+ const (
+ query = `
+ SELECT
+ a.contact_type_id,
+ a.key,
+ a.name
+ FROM tab_contact_type a
+ WHERE a.visible = 1 `
+ )
+
+ rows, err := c.conn.Query(query)
+ if err != nil {
+ return nil, err
+ }
+
+ retVal = make([]entity.ContactType, 0)
+ for rows.Next() {
+ var contactType entity.ContactType
+ err = rows.Scan(&contactType.ID, &contactType.Key, &contactType.Value)
+ if err != nil {
+ return nil, err
+ }
+
+ retVal = append(retVal, contactType)
+ }
+
+ return retVal, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *userRepo) parseEntity(row scanner) (retVal entity.User, err error) {
+ var profile entity.Profile
+ var birthDate mysql.NullTime
+
+ var homeAddress entity.Address
+ var workAddress entity.Address
+
+ err = row.Scan(&retVal.ID, &retVal.UUID, &retVal.Name, &retVal.Member, &birthDate, &retVal.LoginID, &retVal.LoginUUID, &retVal.Email, &retVal.PhoneNumber, &retVal.LoginKey, &retVal.Gender, &retVal.Active, &retVal.Created, &retVal.Updated, &profile.ID, &profile.Name, &profile.Key, &profile.Active, &profile.Blocked, &profile.Suspended, &profile.Created, &profile.Updated, &profile.Organization.ID, &profile.Organization.UUID, &profile.Organization.Type.ID, &profile.Organization.Type.Name, &profile.Organization.Type.Key, &profile.Organization.Type.Description, &profile.Organization.Name, &profile.Organization.Description, &profile.Organization.ReferenceID, &profile.Organization.ParentID, &profile.Organization.Main,
+ &homeAddress.ID, &homeAddress.UUID, &homeAddress.AddressType.ID, &homeAddress.AddressType.Key, &homeAddress.AddressType.Name, &homeAddress.Name, &homeAddress.Address, &homeAddress.Latitude, &homeAddress.Longitude,
+ &workAddress.ID, &workAddress.UUID, &workAddress.AddressType.ID, &workAddress.AddressType.Key, &workAddress.AddressType.Name, &workAddress.Name, &workAddress.Address, &workAddress.Latitude, &workAddress.Longitude)
+ if err != nil {
+ if err != sql.ErrNoRows {
+ return retVal, errors.Wrap(err)
+ }
+ }
+
+ if birthDate.Valid {
+ retVal.BirthDate = birthDate.Time
+ }
+
+ retVal.Profiles = append(retVal.Profiles, profile)
+ if homeAddress.ID > 0 {
+ retVal.Addresses = append(retVal.Addresses, homeAddress)
+ }
+
+ if workAddress.ID > 0 {
+ retVal.Addresses = append(retVal.Addresses, workAddress)
+ }
+
+ return retVal, errors.Wrap(err)
+}
+
+func (c *userRepo) FullLogin(loginType string, key string, pass string, profile string) (user entity.User, err error) {
+ return c.login(loginType, key, pass, profile)
+}
+
+//Login return a user based on email and password with the default `User` profile
+func (c *userRepo) Login(email string, pass string) (user entity.User, err error) {
+ return c.FullLogin("email", email, pass, "US")
+}
+
+func (c *userRepo) getQuery() string {
+ const (
+ query = `SELECT
+ a.user_id,
+ a.user_uuid,
+ a.name,
+ IFNULL(a.member, '') member,
+ a.birth_date,
+ b.login_id,
+ b.login_uuid,
+ IFNULL(b.email, '') email,
+ IFNULL(b.phone_number, '') phone_number,
+ b.key login_key,
+ IFNULL(a.gender, 'U') gender,
+ (IFNULL(a.active, b'0') = b'1') active,
+ a.create_time,
+ a.update_time,
+ e.profile_id,
+ e.name profile_name,
+ e.key profile_key,
+ (IFNULL(c.active, b'0') = b'1') profile_active,
+ (IFNULL(c.blocked, b'0') = b'1') profile_blocked,
+ (IFNULL(c.suspended, b'0') = b'1') profile_suspended,
+ c.create_date profile_createat,
+ c.update_date profile_updateat,
+ IFNULL(f.organization_id, 0) organization_id,
+ IFNULL(f.organization_uuid, '') organization_uuid,
+ IFNULL(f.organization_type_id, 0) organization_type_id,
+ IFNULL(g.organization_type, '') organization_type,
+ IFNULL(g.organization_type_key, '') organization_type_key,
+ IFNULL(g.description, '') organization_type_desc,
+ IFNULL(f.organization_name, '') organization_name,
+ IFNULL(f.organization_description, '') organization_desc,
+ IFNULL(f.organization_reference_id, 0) organization_reference_id,
+ IFNULL(f.organization_parent_id, 0) organization_parent_id,
+ (IFNULL(f.main_organization, b'0') = b'1') main_organization,
+ IFNULL(h.address_id, 0) home_address_id,
+ IFNULL(h.address_uuid, '') home_address_uuid,
+ IFNULL(h.address_type_id, 0) home_address_type_id,
+ IFNULL(h.address_type_key, '') home_address_type_key,
+ IFNULL(h.address_type_name, '') home_address_type_name,
+ IFNULL(h.name, '') home_name,
+ IFNULL(h.address, '') home_address,
+ IFNULL(h.lat, 0) home_lat,
+ IFNULL(h.long, 0) home_long,
+ IFNULL(i.address_id, 0) work_address_id,
+ IFNULL(i.address_uuid, '') work_address_uuid,
+ IFNULL(i.address_type_id, 0) work_address_type_id,
+ IFNULL(i.address_type_key, '') work_address_type_key,
+ IFNULL(i.address_type_name, '') work_address_type_name,
+ IFNULL(i.name, '') work_name,
+ IFNULL(i.address, '') work_address,
+ IFNULL(i.lat, 0) work_lat,
+ IFNULL(i.long, 0) work_long
+ FROM
+ tab_user a
+ INNER JOIN
+ tab_login b ON a.user_id = b.user_id
+ INNER JOIN
+ tab_profile_login c ON c.login_id = b.login_id
+ INNER JOIN
+ tab_profile e ON e.profile_id = c.profile_id
+ LEFT JOIN
+ tab_organization f ON f.organization_id = IFNULL(c.organization_id, 0)
+ LEFT JOIN
+ tab_organization_type g ON IFNULL(g.organization_type_id, 0) = IFNULL(f.organization_type_id, 0)
+ LEFT JOIN
+ viw_address_home h ON a.user_id = h.user_id
+ LEFT JOIN
+ viw_address_work i ON a.user_id = i.user_id
+ WHERE
+ a.active = b.active
+ AND b.active = c.active
+ AND c.active = e.active `
+ )
+
+ return query
+}
+
+func (c *userRepo) login(loginType string, key string, pass string, profile string) (user entity.User, err error) {
+ if loginType == "" {
+ return user, errors.NewNullArgumentError("loginType")
+ }
+
+ if loginType != "phone_number" && loginType != "email" {
+ return user, errors.NewValidationError("loginType", "invalid")
+ }
+
+ query := fmt.Sprintf(c.getQuery()+`
+ AND a.active = 1
+ AND b.%s = ?
+ AND b.password = sha2(?, 512) `, loginType)
+
+ users, err := c.parseSet(c.conn.Query(query, key, pass))
+ if err != nil {
+ return user, errors.Wrap(err)
+ }
+
+ return users[0], nil
+}
+
+func (c *userRepo) Create(user entity.User) (retVal entity.User, err error) {
+ retVal = user
+
+ if retVal.Member != "" {
+ retVal, err = c.getUserByMember(retVal)
+ if err != nil {
+ return retVal, err
+ }
+ }
+
+ if retVal.ID == 0 || retVal.Member == "" {
+ userID, guid, err := c.createUser(user)
+ if err != nil {
+ return retVal, err
+ }
+ retVal.UUID = guid
+ retVal.ID = userID
+ }
+
+ retVal, err = c.getUserLogin(retVal)
+ if err != nil {
+ return retVal, err
+ }
+
+ if retVal.LoginID == 0 {
+ loginID, loginGUID, err := c.createLogin(retVal)
+ if err != nil {
+ return retVal, err
+ }
+ retVal.LoginUUID = loginGUID
+ retVal.LoginID = loginID
+ }
+
+ for _, p := range user.Profiles {
+ companyProfileID, err := c.getCompanyProfile(p.Key)
+ if err != nil {
+ return retVal, err
+ }
+
+ if len(user.Organizations) > 0 {
+ for _, o := range user.Organizations {
+ err = c.addProfileToUser(retVal.LoginID, companyProfileID, o)
+ if err != nil {
+ return retVal, err
+ }
+ }
+ } else {
+ err = c.addProfileToUser(retVal.LoginID, companyProfileID, entity.Organization{})
+ if err != nil {
+ return retVal, err
+ }
+ }
+ }
+
+ if retVal.Email != "" {
+ contact := entity.ContactInfo{
+ Type: entity.ContactType{Key: "email"},
+ Value: retVal.Email,
+ UserID: retVal.ID,
+ }
+
+ contact, err = c.addContactInfo(contact)
+ if err != nil {
+ return retVal, err
+ }
+ }
+
+ if retVal.PhoneNumber != "" {
+ contact := entity.ContactInfo{
+ Type: entity.ContactType{Key: "phone"},
+ Value: retVal.PhoneNumber,
+ UserID: retVal.ID,
+ }
+
+ contact, err = c.addContactInfo(contact)
+ if err != nil {
+ return retVal, err
+ }
+ }
+
+ return c.GetByUUID(retVal.UUID, "")
+}
+
+func (c *userRepo) SaveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
+ return c.addContactInfo(contact)
+}
+
+func (c *userRepo) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
+ const (
+ query = `INSERT INTO tab_contact(contact_type_id, user_id, contact)
+ SELECT a.contact_type_id, ? user_id, ? contact
+ FROM
+ tab_contact_type a
+ LEFT JOIN tab_contact b
+ ON a.contact_type_id = b.contact_type_id
+ AND b.user_id = ?
+ AND b.contact = ?
+ WHERE a.key = ?
+ AND b.contact_id IS NULL;`
+ )
+
+ result, err := c.conn.Exec(query, contact.UserID, contact.Value, contact.UserID, contact.Value, contact.Type.Key)
+ if err != nil {
+ return contact, err
+ }
+
+ retVal := contact
+ retVal.ID, err = result.LastInsertId()
+ if err != nil {
+ return contact, err
+ }
+
+ return retVal, nil
+}
+
+func (c *userRepo) addContactInfo(contact entity.ContactInfo) (entity.ContactInfo, error) {
+ const (
+ query = `INSERT INTO tab_contact(contact_type_id, user_id, contact)
+ SELECT a.contact_type_id, ? user_id, ? contact
+ FROM
+ tab_contact_type a
+ LEFT JOIN tab_contact b
+ ON a.contact_type_id = b.contact_type_id
+ AND b.user_id = ?
+ AND b.contact = ?
+ WHERE a.key = ?
+ AND b.contact_id IS NULL;`
+ )
+
+ result, err := c.conn.Exec(query, contact.UserID, contact.Value, contact.UserID, contact.Value, contact.Type.Key)
+ if err != nil {
+ return contact, err
+ }
+
+ retVal := contact
+ retVal.ID, err = result.LastInsertId()
+ if err != nil {
+ return contact, err
+ }
+
+ return retVal, nil
+}
+
+func (c *userRepo) getUserByLoginAndProfile(loginID int64) (user entity.User, err error) {
+ finalQuery := c.getQuery() + " AND a.active = 1 AND b.login_Id = ? "
+
+ users, err := c.parseSet(c.conn.Query(finalQuery, loginID))
+ if err != nil {
+ return user, errors.Wrap(err)
+ }
+
+ return users[0], nil
+}
+
+func (c *userRepo) addProfileToUser(loginID int64, profileID int64, organization entity.Organization) error {
+ const query = "INSERT INTO tab_profile_login(profile_id, login_id, active, blocked, suspended, organization_id) VALUES(?, ?, 1, 0, 0, ?) ON DUPLICATE KEY UPDATE profile_id = ?, login_id = ?, organization_id = ?;"
+ const checkQuery = "SELECT COUNT(1) has_profile FROM tab_profile_login a WHERE a.login_id = ? AND a.profile_id = ? AND IFNULL(a.organization_id, 0) = ?;"
+
+ var total int64
+ row := c.conn.QueryRow(checkQuery, loginID, profileID, organization.ID)
+ err := row.Scan(&total)
+ if err != nil && err != sql.ErrNoRows {
+ return err
+ }
+
+ if total < 1 {
+ _, err := c.conn.Exec(query, profileID, loginID, organization.ID, profileID, loginID, toNullInt64(organization.ID))
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (c *userRepo) getUserByMember(u entity.User) (user entity.User, err error) {
+ user = u
+ users, err := c.parseSet(c.conn.Query(c.getQuery()+" AND a.active = 1 AND e.key = 'US' AND IFNULL(a.member, '') = ?;", u.Member))
+ if err != nil {
+ return user, errors.Wrap(err)
+ }
+
+ if users[0].ID != 0 {
+ user = users[0]
+ }
+ return user, nil
+}
+
+func (c *userRepo) getCompanyProfile(profile string) (int64, error) {
+ const (
+ query = "SELECT a.profile_id FROM tab_profile a WHERE a.key = ?;"
+ )
+ var companyProfileID int64
+ row := c.conn.QueryRow(query, profile)
+ err := row.Scan(&companyProfileID)
+ if err != nil {
+ return 0, err
+ }
+
+ return companyProfileID, nil
+}
+
+func (c *userRepo) getUserLogin(u entity.User) (user entity.User, err error) {
+ const (
+ query = "SELECT login_id, login_uuid, user_id, IFNULL(phone_number, '') phone_number, IFNULL(email, '') email, `key`, `password` FROM tab_login WHERE user_id = ?"
+ )
+
+ row := c.conn.QueryRow(query, user.Member)
+ err = row.Scan(&user.LoginID, &user.LoginUUID, &user.ID, &user.PhoneNumber, &user.Email, &user.LoginKey, &user.Pass)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return u, nil
+ } else {
+ return user, err
+ }
+ }
+
+ return user, nil
+}
+
+func (c *userRepo) createLogin(user entity.User) (int64, string, error) {
+ const (
+ query = "INSERT INTO tab_login (login_uuid, user_id, phone_number, email, `key`, `password`) VALUES(?, ?, ?, ?, ?, sha2(?, 512)) ON DUPLICATE KEY UPDATE login_uuid = ?, user_id = ?, phone_number = ?, email = ?, `key` = ?, `password` = sha2(?, 512);"
+ )
+ guid, _ := uuid.NewV4()
+ key, _ := uuid.NewV4()
+
+ result, err := c.conn.Exec(query, guid.String(), user.ID, toNullString(user.PhoneNumber), toNullString(user.Email), key.String(), user.Pass, guid.String(), user.ID, user.PhoneNumber, user.Email, key.String(), user.Pass)
+ if err != nil {
+ return 0, "", err
+ }
+
+ loginID, err := result.LastInsertId()
+ if err != nil {
+ return 0, "", err
+ }
+
+ return loginID, guid.String(), nil
+}
+
+func (c *userRepo) createUser(user entity.User) (int64, string, error) {
+ const (
+ query = "INSERT INTO tab_user(user_uuid, `name`, member, birth_date, gender) VALUES(?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE user_uuid = ?, `name` = ?, member = ?, birth_date = ?, gender = ?;"
+ )
+ guid, _ := uuid.NewV4()
+
+ result, err := c.conn.Exec(query, guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender), guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender))
+ if err != nil {
+ return 0, "", err
+ }
+
+ userID, err := result.LastInsertId()
+ if err != nil {
+ return 0, "", err
+ }
+
+ return userID, guid.String(), nil
+}
+
+func (c *userRepo) RemoveAddress(addressUUID string) error {
+ const (
+ query = "UPDATE tab_address SET active = 0 WHERE address_uuid = ?"
+ )
+
+ _, err := c.conn.Exec(query, addressUUID)
+ return err
+}
+
+func (c *userRepo) SaveAddress(address entity.Address) (entity.Address, error) {
+ const (
+ query = "INSERT INTO tab_address(address_uuid,address_type_id,address_origin_id,user_id,internal_id,`name`,address,lat,`long`,created_user_id) VALUES (?,?,?,?,?,?,?,?,?,?);"
+ )
+
+ address, err := c.getAddressSecondaryData(address)
+ if err != nil {
+ return address, err
+ }
+
+ uuid, _ := uuid.NewV4()
+ address.UUID = uuid.String()
+
+ result, err := c.conn.Exec(query, address.UUID, address.AddressType.ID, address.Origin.ID, address.User.ID, address.InternalID, address.Name, address.Address, address.Latitude, address.Longitude, address.CreatedUser.ID)
+ if err != nil {
+ return address, err
+ }
+
+ addressID, err := result.LastInsertId()
+ if err != nil {
+ return address, err
+ }
+
+ return c.getAddressByID(addressID)
+}
+
+func (c *userRepo) getAddressByUserID(userID int64) ([]entity.Address, error) {
+ const (
+ query = `SELECT
+ a.address_id,
+ a.address_uuid,
+ a.address_type_id,
+ d.key address_type_key,
+ d.name address_type_name,
+ a.address_origin_id,
+ e.key address_origin_key,
+ e.name address_origin_name,
+ b.user_id,
+ b.user_uuid,
+ b.name user_name,
+ a.internal_id,
+ a.name,
+ a.address,
+ a.lat,
+ a.long,
+ c.user_id created_user_id,
+ c.user_uuid created_user_uuid,
+ c.name created_user_name
+ FROM
+ tab_address a
+ INNER JOIN tab_user b
+ ON a.user_id = b.user_id
+ INNER JOIN tab_user c
+ ON a.created_user_id = c.user_id
+ INNER JOIN tab_address_type d
+ ON a.address_type_id = d.address_type_id
+ INNER JOIN tab_address_origin e
+ ON a.address_origin_id = e.address_origin_id
+ WHERE
+ a.user_id = ? and a.active = 1;`
+ )
+
+ var addresses []entity.Address
+ rows, err := c.conn.Query(query, userID)
+ if err != nil {
+ return nil, err
+ }
+
+ for rows.Next() {
+ var address entity.Address
+ err := rows.Scan(&address.ID, &address.UUID, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name,
+ &address.Origin.ID, &address.Origin.Key, &address.Origin.Name, &address.User.ID, &address.User.UUID, &address.User.Name,
+ &address.InternalID, &address.Name, &address.Address, &address.Latitude, &address.Longitude, &address.CreatedUser.ID,
+ &address.CreatedUser.UUID, &address.CreatedUser.Name)
+ if err != nil {
+ return nil, err
+ }
+ addresses = append(addresses, address)
+ }
+ return addresses, nil
+}
+
+func (c *userRepo) getAddressByID(addressID int64) (entity.Address, error) {
+ const (
+ query = `SELECT
+ a.address_id,
+ a.address_uuid,
+ a.address_type_id,
+ d.key address_type_key,
+ d.name address_type_name,
+ a.address_origin_id,
+ e.key address_origin_key,
+ e.name address_origin_name,
+ b.user_id,
+ b.user_uuid,
+ b.name user_name,
+ a.internal_id,
+ a.name,
+ a.address,
+ a.lat,
+ a.long,
+ c.user_id created_user_id,
+ c.user_uuid created_user_uuid,
+ c.name created_user_name
+ FROM
+ tab_address a
+ INNER JOIN tab_user b
+ ON a.user_id = b.user_id
+ INNER JOIN tab_user c
+ ON a.created_user_id = c.user_id
+ INNER JOIN tab_address_type d
+ ON a.address_type_id = d.address_type_id
+ INNER JOIN tab_address_origin e
+ ON a.address_origin_id = e.address_origin_id
+ WHERE
+ a.address_id = ?;`
+ )
+
+ var address entity.Address
+ row := c.conn.QueryRow(query, addressID)
+ err := row.Scan(&address.ID, &address.UUID, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name,
+ &address.Origin.ID, &address.Origin.Key, &address.Origin.Name, &address.User.ID, &address.User.UUID, &address.User.Name,
+ &address.InternalID, &address.Name, &address.Address, &address.Latitude, &address.Longitude, &address.CreatedUser.ID,
+ &address.CreatedUser.UUID, &address.CreatedUser.Name)
+ if err != nil {
+ return entity.Address{}, err
+ }
+
+ return address, nil
+}
+
+func (c *userRepo) GetAddressByUUID(addressUUID string) (entity.Address, error) {
+ const (
+ query = `SELECT
+ a.address_id,
+ a.address_uuid,
+ a.address_type_id,
+ d.key address_type_key,
+ d.name address_type_name,
+ a.address_origin_id,
+ e.key address_origin_key,
+ e.name address_origin_name,
+ b.user_id,
+ b.user_uuid,
+ b.name user_name,
+ a.internal_id,
+ a.name,
+ a.address,
+ a.lat,
+ a.long,
+ c.user_id created_user_id,
+ c.user_uuid created_user_uuid,
+ c.name created_user_name
+ FROM
+ tab_address a
+ INNER JOIN tab_user b
+ ON a.user_id = b.user_id
+ INNER JOIN tab_user c
+ ON a.created_user_id = c.user_id
+ INNER JOIN tab_address_type d
+ ON a.address_type_id = d.address_type_id
+ INNER JOIN tab_address_origin e
+ ON a.address_origin_id = e.address_origin_id
+ WHERE
+ a.address_uuid = ?;`
+ )
+
+ var address entity.Address
+ row := c.conn.QueryRow(query, addressUUID)
+ err := row.Scan(&address.ID, &address.UUID, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name,
+ &address.Origin.ID, &address.Origin.Key, &address.Origin.Name, &address.User.ID, &address.User.UUID, &address.User.Name,
+ &address.InternalID, &address.Name, &address.Address, &address.Latitude, &address.Longitude, &address.CreatedUser.ID,
+ &address.CreatedUser.UUID, &address.CreatedUser.Name)
+ if err != nil {
+ return entity.Address{}, err
+ }
+
+ return address, nil
+}
+
+func (c *userRepo) getAddressSecondaryData(address entity.Address) (entity.Address, error) {
+ const (
+ query = `SELECT
+ a.user_id,
+ a.user_uuid,
+ a.name user_name,
+ b.user_id created_user_id,
+ b.user_uuid created_user_uuid,
+ b.name created_user_name,
+ c.address_type_id,
+ c.key address_type_key,
+ c.name address_type_name,
+ d.address_origin_id,
+ d.key address_origin_key,
+ d.name address_origin_name
+ FROM
+ tab_user a,
+ tab_user b,
+ tab_address_type c,
+ tab_address_origin d
+ WHERE
+ a.user_uuid = ?
+ AND b.user_uuid = ?
+ AND c.key = ?
+ AND d.key = ?;`
+ )
+
+ row := c.conn.QueryRow(query, address.User.UUID, address.CreatedUser.UUID, address.AddressType.Key, address.Origin.Key)
+ err := row.Scan(&address.User.ID, &address.User.UUID, &address.User.Name, &address.CreatedUser.ID, &address.CreatedUser.UUID, &address.CreatedUser.Name, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name, &address.Origin.ID, &address.Origin.Key, &address.Origin.Name)
+ if err != nil {
+ return address, err
+ }
+
+ return address, nil
+}
+
+// GetAll returns a list of all active cards
+func (c *userRepo) GetAll() (list []entity.User, err error) {
+ return c.parseSet(c.conn.Query(c.getQuery() + " WHERE a.active = 1 "))
+}
+
+// GetByID returns a single card data by its ID
+func (c *userRepo) GetByID(userID int64) (retVal entity.User, err error) {
+ user, err := c.parseSet(c.conn.Query(c.getQuery()+" AND a.user_id = ? ", userID))
+ if err != nil {
+ return entity.User{}, err
+ }
+
+ if len(user) > 0 {
+ retVal := user[0]
+ retVal.Contacts, err = c.GetContacts(retVal.ID)
+ if err != nil {
+ return entity.User{}, err
+ }
+
+ retVal.Addresses = nil
+ retVal.Addresses, err = c.getAddressByUserID(retVal.ID)
+ if err != nil {
+ return entity.User{}, err
+ }
+ return retVal, nil
+ } else {
+ return retVal, nil
+ }
+}
+
+func toNullString(s string) sql.NullString {
+ return sql.NullString{String: s, Valid: s != ""}
+}
+
+func toNullInt64(i int64) sql.NullInt64 {
+ return sql.NullInt64{Int64: i, Valid: i > 0}
+}
+
+func toNullTime(date time.Time) mysql.NullTime {
+ return mysql.NullTime{Time: date, Valid: !date.IsZero()}
+}
diff --git a/data/datamysql/utils.go b/data/datamysql/utils.go
new file mode 100644
index 0000000..7153665
--- /dev/null
+++ b/data/datamysql/utils.go
@@ -0,0 +1,15 @@
+package datamysql
+
+import (
+ "database/sql"
+)
+
+type scanner interface {
+ Scan(dest ...interface{}) error
+}
+
+type executor interface {
+ Exec(query string, args ...interface{}) (sql.Result, error)
+ QueryRow(query string, args ...interface{}) *sql.Row
+ Query(query string, args ...interface{}) (*sql.Rows, error)
+}
diff --git a/data/datamysql/visit.go b/data/datamysql/visit.go
new file mode 100644
index 0000000..e13e057
--- /dev/null
+++ b/data/datamysql/visit.go
@@ -0,0 +1,210 @@
+package datamysql
+
+import (
+ "database/sql"
+ "fmt"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/go-sql-driver/mysql"
+ uuid "github.com/satori/go.uuid"
+)
+
+// visitRepo maps methods to database
+type visitRepo struct {
+ conn executor
+}
+
+func newVisitRepo(conn executor) *visitRepo {
+ return &visitRepo{
+ conn: conn,
+ }
+}
+
+func (c *visitRepo) getProfileQuery(user entity.User) (query string, where string, err error) {
+ if len(user.Profiles) > 0 {
+ for _, p := range user.Profiles {
+ switch p.Key {
+ case "AD", "BCBSIAD", "BDCAD", "PLANAD":
+ return
+ case "SP", "SPT":
+ switch p.Organization.Type.Key {
+ case "techsupport", "bcbsi", "bcbsa", "plan":
+ return
+ case "provider":
+ query = ` INNER JOIN viw_visit_provider f
+ ON f.visit_id = a.visit_id `
+ where = fmt.Sprintf(` AND (f.organization_uuid = '%s' OR f.parent_organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
+ return
+ }
+ }
+ }
+
+ if query == "" && where == "" {
+ return "", "", fmt.Errorf("Invalid Query")
+ } else {
+ return
+ }
+ } else {
+ return "", "", fmt.Errorf("User has no profile to search")
+ }
+}
+
+func (c *visitRepo) getQuery() string {
+ return `SELECT
+ a.visit_id,
+ a.visit_uuid,
+ a.visit_status_id,
+ b.visit_status_key,
+ b.visit_status,
+ a.user_id,
+ c.user_uuid,
+ c.name user_name,
+ c.member user_member,
+ c.birth_date user_birth_date,
+ c.gender user_gender,
+ a.visit_datetime,
+ a.pickup_datetime,
+ IFNULL(a.notes, '') notes,
+ a.created_user_id,
+ d.user_uuid created_user_uuid,
+ d.name created_user_name,
+ a.created_date,
+ a.updated_date,
+ IFNULL(a.visit_duration, 0) visit_duration,
+ a.visit_external_id,
+ e.trip_type_id,
+ e.trip_type_key,
+ e.trip_type,
+ IFNULL(a.pickup_id, '') visit_pickup_id,
+ IFNULL(a.pickup_address_id, 0) pickup_address_id,
+ IFNULL(a.address_id, 0) address_id,
+ IFNULL(a.provider_id, 0) provider_id,
+ IFNULL(f.provider_uuid, '') provider_uuid,
+ IFNULL(f.provider_internal_id, '') provider_internal_id,
+ IFNULL(f.provider_muk_id, '') provider_muk_id,
+ IFNULL(f.provider_name, '') provider_name
+ FROM
+ tab_visit a
+ INNER JOIN tab_visit_status b
+ ON a.visit_status_id = b.visit_status_id
+ INNER JOIN tab_user c
+ ON c.user_id = a.user_id
+ INNER JOIN tab_user d
+ ON d.user_id = a.created_user_id
+ INNER JOIN tab_trip_type e
+ ON e.trip_type_id = a.trip_type_id
+ INNER JOIN tab_provider f
+ ON f.provider_id = a.provider_id `
+}
+
+func (c *visitRepo) GetAll(user entity.User) ([]entity.Visit, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return nil, err
+ }
+
+ query = c.getQuery() + query + " WHERE 1 = 1 and c.active = 1 " + where
+
+ return c.parseSet(c.conn.Query(query))
+}
+
+func (c *visitRepo) GetByUUID(visitUUID string, user entity.User) (entity.Visit, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return entity.Visit{}, err
+ }
+
+ query = c.getQuery() + query + " WHERE a.visit_uuid = ? " + where
+ return c.parseEntity(c.conn.QueryRow(query, visitUUID))
+}
+
+func (c *visitRepo) GetByID(visitID int64, user entity.User) (entity.Visit, error) {
+ query, where, err := c.getProfileQuery(user)
+ if err != nil {
+ return entity.Visit{}, err
+ }
+
+ query = c.getQuery() + query + " WHERE a.visit_id = ? " + where
+ return c.parseEntity(c.conn.QueryRow(query, visitID))
+}
+
+// parseSet parses a result set result to an entity array
+func (c *visitRepo) parseSet(rows *sql.Rows, err error) ([]entity.Visit, error) {
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result := make([]entity.Visit, 0)
+ for rows.Next() {
+ entity, err := c.parseEntity(rows)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+ result = append(result, entity)
+ }
+ return result, nil
+}
+
+// parseEntity parses a result to an entity
+func (c *visitRepo) parseEntity(row scanner) (retVal entity.Visit, err error) {
+ var birthDate mysql.NullTime
+ var gender sql.NullString
+
+ err = row.Scan(
+ &retVal.ID, &retVal.UUID, &retVal.Status.ID, &retVal.Status.Key, &retVal.Status.Value, &retVal.User.ID, &retVal.User.UUID, &retVal.User.Name, &retVal.User.Member, &birthDate, &gender, &retVal.VisitDatetime, &retVal.PickupDatetime, &retVal.Notes, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.Created, &retVal.Updated, &retVal.VisitDuration, &retVal.ExternalID, &retVal.TripType.ID, &retVal.TripType.Key, &retVal.TripType.Value, &retVal.Pickup.ID, &retVal.PickupAddressID, &retVal.DestinationAddressID, &retVal.Provider.ProviderID, &retVal.Provider.ProviderUUID, &retVal.Provider.InternalID, &retVal.Provider.MukID, &retVal.Provider.Name)
+
+ if birthDate.Valid {
+ retVal.User.BirthDate = birthDate.Time
+ }
+
+ if gender.Valid {
+ retVal.User.Gender = gender.String
+ } else {
+ retVal.User.Gender = "U"
+ }
+
+ return retVal, errors.Wrap(err)
+}
+
+func (c *visitRepo) Create(visit entity.Visit) (entity.Visit, error) {
+ const (
+ statusQuery = `SELECT a.visit_status_id, a.visit_status_key, a.visit_status, b.user_id, b.name user_name, c.user_id create_user_id, c.name create_user_name, d.trip_type_id, d.trip_type_key, d.trip_type FROM tab_visit_status a, tab_user b, tab_user c, tab_trip_type d WHERE a.visit_status_key = ? AND b.user_uuid = ? AND c.user_uuid = ? AND d.trip_type_key = ?;`
+ query = `INSERT INTO tab_visit(visit_uuid, visit_status_id, user_id, visit_datetime, pickup_datetime, notes, created_user_id, visit_duration, visit_external_id, return_date, trip_type_id, pickup_id, pickup_address_id, address_id, provider_id)
+ VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`
+ )
+
+ retVal := visit
+
+ returnDate := mysql.NullTime{
+ Valid: (retVal.ReturnDate != nil),
+ }
+ if retVal.ReturnDate != nil {
+ returnDate.Time = *retVal.ReturnDate
+ }
+
+ UUID, _ := uuid.NewV4()
+ retVal.UUID = UUID.String()
+
+ if retVal.Status.Key == "" {
+ retVal.Status.Key = "accepted"
+ }
+
+ row := c.conn.QueryRow(statusQuery, retVal.Status.Key, retVal.User.UUID, retVal.CreatedUser.UUID, retVal.TripType.Key)
+ if err := row.Scan(&retVal.Status.ID, &retVal.Status.Key, &retVal.Status.Value, &retVal.User.ID, &retVal.User.Name, &retVal.CreatedUser.ID, &retVal.CreatedUser.Name, &retVal.TripType.ID, &retVal.TripType.Key, &retVal.TripType.Value); err != nil {
+ fmt.Println("Error to get base data: ", err.Error())
+ return retVal, err
+ }
+
+ results, err := c.conn.Exec(query, retVal.UUID, retVal.Status.ID, retVal.User.ID, retVal.VisitDatetime, retVal.PickupDatetime, retVal.Notes, retVal.CreatedUser.ID, toNullInt64(retVal.VisitDuration), retVal.ExternalID, returnDate, retVal.TripType.ID, retVal.Pickup.ID, retVal.PickupAddressID, retVal.DestinationAddressID, retVal.Provider.ProviderID)
+ if err != nil {
+ return retVal, err
+ }
+
+ retVal.ID, err = results.LastInsertId()
+ if err != nil {
+ return retVal, err
+ }
+
+ fmt.Println("Visit ID: ", retVal.ID)
+ return retVal, nil
+}
diff --git a/docs/swagger/nemt-portal-api.yaml b/docs/swagger/nemt-portal-api.yaml
new file mode 100644
index 0000000..a9e464b
--- /dev/null
+++ b/docs/swagger/nemt-portal-api.yaml
@@ -0,0 +1,1211 @@
+swagger: "2.0"
+info:
+ version: "1.0.2"
+ title: NEMT Member API
+ description: |
+ RESTful API for NEMT Member App
+ Repo: nemt-portal-api
+
+ Use the lockpad icon on the right side of a route to authorize the route.
+ contact:
+ name: Carlos Andrioli
+ email: carlos@brighterdevelopment.com
+basePath: /v1
+schemes:
+ - http
+consumes:
+ - application/json
+produces:
+ - application/json
+securityDefinitions:
+ AppKey:
+ type: apiKey
+ in: header
+ name: App
+ description: Application Key (use "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") only used to authenticate the application
+ AppToken:
+ type: apiKey
+ in: header
+ name: Token
+ description: The App Bearer token. Need to make a get request to the address "/v1/authenticate" with the "App" header and the log in body
+tags:
+ - name: auth
+ description: Endpoints for system and users authentication.
+ - name: member
+ description: Endpoints for members of a participating payer.
+ - name: visits
+ description: Endpoints for visits to participating providers by members of a participating payer.
+ - name: notifications
+ description: Endpoints for notifications related to members, visits, providers and system state.
+ - name: rides
+ description: Endpoints for rides to participating providers for members of participating payers.
+ - name: providers
+ description: Endpoints for participating providers related to a member of a participating payer
+ - name: messages
+ description: Endpoints for (tbd) message types.
+paths:
+ /authenticate/:
+ post:
+ tags:
+ - auth
+ summary: Authorize the application use
+ description: Authorizes the application routes returning a JWT token for authentication
+ operationId: authenticateApp
+ security:
+ - AppKey: []
+ parameters:
+ - name: data
+ in: body
+ description: Member authentication data
+ required: true
+ schema:
+ $ref: '#/definitions/AuthRequest'
+ responses:
+ 200:
+ description: Get the token for application authorization
+ schema:
+ $ref: '#/definitions/AuthResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/visits/:
+ get:
+ tags:
+ - visits
+ - member
+ summary: Get a filtered list of member-visits to participating providers
+ description: Get a list of visits
+ operationId: listVisits
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Visits paginated list
+ schema:
+ $ref: '#/definitions/VisitsPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ post:
+ tags:
+ - visits
+ - member
+ summary: Create a visit to a participating provider for an eligible member.
+ description: Reserves a pre-defined or arbitrary visit time range
+ operationId: addVisit
+ security:
+ - AppToken: []
+ parameters:
+ - name: data
+ in: body
+ description: Visit data
+ required: true
+ schema:
+ $ref: '#/definitions/Visit'
+ responses:
+ 200:
+ description: Visit object with all the ID and remanescent parameters filled
+ schema:
+ $ref: '#/definitions/Visit'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/visits/{visit_uuid}/:
+ get:
+ tags:
+ - visits
+ - member
+ summary: Get details of a single member-visit to a participating provider.
+ description: Get details of a single member-provider visit
+ operationId: getVisitDetail
+ security:
+ - AppToken: []
+ parameters:
+ - name: visit_uuid
+ in: path
+ description: Visit unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: Visit Details
+ schema:
+ $ref: '#/definitions/Visit'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ put:
+ tags:
+ - visits
+ - member
+ summary: Update a single member-visit to a participating provider.
+ description: Get the member visit
+ operationId: updatemember
+ security:
+ - AppToken: []
+ parameters:
+ - name: visit_uuid
+ in: path
+ description: Visit unique identifier
+ type: string
+ required: true
+ - name: data
+ in: body
+ description: Visit data
+ required: true
+ schema:
+ $ref: '#/definitions/Visit'
+ responses:
+ 200:
+ description: Visit detail
+ schema:
+ $ref: '#/definitions/Visit'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ delete:
+ tags:
+ - visits
+ - member
+ summary: Delete a single member-visit to a participating provider.
+ description: Cancel a member appointment
+ operationId: deletemember
+ security:
+ - AppToken: []
+ parameters:
+ - name: visit_uuid
+ in: path
+ description: Visit unique identifier
+ type: string
+ required: true
+ responses:
+ 204:
+ description: No return if everything works
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/members/:
+ get:
+ tags:
+ - member
+ summary: Get a filtered list of members
+ description: Get a list of members
+ operationId: listmembers
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: members paginated list
+ schema:
+ $ref: '#/definitions/MembersPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/members/{member_uuid}/:
+ get:
+ tags:
+ - member
+ summary: member detail
+ description: Get a member's detail data
+ operationId: getmemberDetail
+ security:
+ - AppToken: []
+ parameters:
+ - name: member_uuid
+ in: path
+ description: member unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: member detail
+ schema:
+ $ref: '#/definitions/Member'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/notifications/:
+ get:
+ tags:
+ - notifications
+ - member
+ summary: Get a list of notifications for a single member.
+ description: Get a list of notifications for a single member.
+ operationId: listNotifications
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Notification paginated list
+ schema:
+ $ref: '#/definitions/NotificationPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/notifications/{notification_uuid}/:
+ get:
+ tags:
+ - notifications
+ - member
+ summary: Get the member's notification
+ description: Get a specific notification
+ operationId: getNotification
+ security:
+ - AppToken: []
+ parameters:
+ - name: notification_uuid
+ in: path
+ description: Notification unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: Notification detail
+ schema:
+ $ref: '#/definitions/Notification'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/:
+ get:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Get a filtered list of rides for a single member.
+ description: Get a filtered list of rides for a single member.
+ operationId: listRides
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Rides paginated list
+ schema:
+ $ref: '#/definitions/RidePaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ post:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Create a ride to a participating provider for an eligible member.
+ description: Get the ride
+ operationId: addRide
+ security:
+ - AppToken: []
+ parameters:
+ - name: data
+ in: body
+ description: Book a scheduled ride with at lease one ride_segment.
+ required: true
+ schema:
+ $ref: '#/definitions/RideRequest'
+ responses:
+ 200:
+ description: Ride object with all the ID and remanescent parameters filled
+ schema:
+ $ref: '#/definitions/Ride'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/{ride_uuid}/:
+ get:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Ride detail
+ description: Get a member's specific ride data
+ operationId: getRideDetail
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: Ride detail
+ schema:
+ $ref: '#/definitions/Ride'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ put:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Update member ride
+ description: Get the member ride
+ operationId: updateRides
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ - name: data
+ in: body
+ description: Ride data
+ required: true
+ schema:
+ $ref: '#/definitions/Ride'
+ responses:
+ 200:
+ description: Ride detail
+ schema:
+ $ref: '#/definitions/Ride'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/{ride_uuid}/cancel:
+ post:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Cancel ride
+ description: Cancel a specific ride for a member
+ operationId: cancelRide
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ responses:
+ 204:
+ description: Empty response means that the cancel was aceppted
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/{ride_uuid}/destination:
+ put:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Change the ride destination
+ description: Change the ride destination
+ operationId: changeRideDestination
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ - name: data
+ in: body
+ description: Destination data
+ required: true
+ schema:
+ $ref: '#/definitions/Location'
+ responses:
+ 200:
+ description: Location confirmation
+ schema:
+ $ref: '#/definitions/Location'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/ridetypes:
+ get:
+ tags:
+ - rides
+ security:
+ - AppToken: []
+ operationId: getRideTypes
+ summary: List the ride types
+ description: List the ride types from the database
+ parameters:
+ - name: lat
+ in: query
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: query
+ description: longitude
+ type: number
+ format: float
+ required: true
+ responses:
+ 200:
+ description: Ride Type list
+ schema:
+ $ref: '#/definitions/RideTypeResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rideseta:
+ get:
+ tags:
+ - rides
+ security:
+ - AppToken: []
+ operationId: getRideEta
+ summary: Get the ETA of the Ride
+ description: Get the ETA of the types
+ parameters:
+ - name: lat
+ in: query
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: query
+ description: longitude
+ type: number
+ format: float
+ required: true
+ - name: dest_lat
+ in: query
+ description: destination latitude
+ type: number
+ format: float
+ required: true
+ - name: dest_lng
+ in: query
+ description: destination longitude
+ type: number
+ format: float
+ required: true
+ - name: ride_type_uuid
+ in: query
+ description: ride type UUID
+ type: string
+ responses:
+ 200:
+ description: Ride ETA list
+ schema:
+ $ref: '#/definitions/RideETAResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/ridedrivers:
+ get:
+ tags:
+ - rides
+ security:
+ - AppToken: []
+ operationId: getRideDrivers
+ summary: Get the Drivers close to the location
+ description: Get the Drivers close to the location
+ parameters:
+ - name: lat
+ in: query
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: query
+ description: longitude
+ type: number
+ format: float
+ required: true
+ - name: ride_type_uuid
+ in: query
+ description: ride type UUID
+ type: string
+ responses:
+ 200:
+ description: Ride Drivers list
+ schema:
+ $ref: '#/definitions/RideDriverResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/providers/:
+ get:
+ tags:
+ - rides
+ - providers
+ - member
+ summary: Get providers
+ description: Get a list of providers
+ operationId: getProviders
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Provider list
+ schema:
+ $ref: '#/definitions/ProviderPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/providers/{lat}/{lng}/:
+ get:
+ tags:
+ - rides
+ - providers
+ - member
+ summary: Provider by Location
+ description: Get a list of providers for a current location
+ operationId: getProvidersByLocation
+ security:
+ - AppToken: []
+ parameters:
+ - name: lat
+ in: path
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: path
+ description: longitude
+ type: number
+ format: float
+ required: true
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Provider list
+ schema:
+ $ref: '#/definitions/ProviderPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+definitions:
+ DefaultErrorResponse:
+ type: object
+ description: Default error response data
+ properties:
+ error:
+ type: boolean
+ description: Indicates if the response is an error
+ message:
+ type: string
+ description: Detailed response message
+ AuthRequest:
+ type: object
+ description: Request from application authrization
+ properties:
+ email:
+ type: string
+ description: Member e-mail
+ password:
+ type: string
+ description: Base64 encoded password
+ AuthResponse:
+ type: object
+ description: Response from application authrization
+ properties:
+ token:
+ type: string
+ description: The token string for app authorization
+ valid_time:
+ type: integer
+ format: int64
+ description: Token expiration time in Unix time format
+ server_time:
+ type: integer
+ format: int64
+ description: Server time in Unix time format
+ PaginatedResponse:
+ type: object
+ description: Paginated response data
+ properties:
+ pagination:
+ type: object
+ description: Pagination data
+ properties:
+ total_records:
+ type: integer
+ format: int64
+ description: Total result count
+ records_per_page:
+ type: integer
+ format: int64
+ description: Max records per page
+ total_pages:
+ type: integer
+ format: int64
+ description: Total page count
+ current_page:
+ type: integer
+ format: int64
+ description: Current page number
+ data:
+ type: array
+ items:
+ type: object
+ description: Paginaged data
+ Member:
+ type: object
+ description: member data
+ properties:
+ member_uuid:
+ type: string
+ description: member unique ID
+ name:
+ type: string
+ description: Name
+ phone_number:
+ type: string
+ description: Phone number
+ MembersPaginatedResponse:
+ type: object
+ description: members paginated response data
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Member'
+ Driver:
+ type: object
+ description: Driver data
+ properties:
+ driver_uuid:
+ type: string
+ description: Driver unique ID
+ name:
+ type: string
+ description: Name
+ phone_number:
+ type: string
+ description: Phone number
+ vehicle:
+ type: object
+ description: Driver car description
+ $ref: '#/definitions/Vehicle'
+ Vehicle:
+ type: object
+ description: Veicule data
+ properties:
+ vehicle_uuid:
+ type: string
+ description: Vehicle unique ID
+ make:
+ type: string
+ description: Car brand
+ model:
+ type: string
+ description: Car model
+ plate:
+ type: string
+ description: Car plate
+ color:
+ type: string
+ description: Car color
+ Visit:
+ type: object
+ description: Visit data (Still TBD by the Data Model)
+ properties:
+ visit_uuid:
+ type: string
+ description: Visit unique ID
+ VisitsPaginatedResponse:
+ type: object
+ description: Visits paginated response data
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Visit'
+ Notification:
+ type: object
+ description: Notification data
+ properties:
+ notification_uuid:
+ type: string
+ description: Notification unique ID
+ notification:
+ type: string
+ description: Notification message
+ is_read:
+ type: boolean
+ description: Verify if the message was read
+ NotificationPaginatedResponse:
+ type: object
+ description: Notification paginated response data
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Notification'
+ RideRequest:
+ type: object
+ description: Visit data
+ properties:
+ ride_type:
+ type: object
+ description: Ride type
+ $ref: '#/definitions/RideType'
+ schedule_date:
+ type: string
+ format: datetime
+ description: Request date
+ coordinates:
+ type: object
+ description: Coordinates information
+ $ref: '#/definitions/RideCoordinates'
+ Ride:
+ type: object
+ description: Visit data
+ properties:
+ ride_uuid:
+ type: string
+ description: Ride unique ID
+ ride_type:
+ type: object
+ description: Ride type
+ $ref: '#/definitions/RideType'
+ ride_status:
+ type: object
+ description: Ride status
+ $ref: '#/definitions/RideStatus'
+ request_at:
+ type: string
+ format: datetime
+ description: Request date
+ driver:
+ type: object
+ description: Driver information
+ $ref: '#/definitions/Driver'
+ coordinates:
+ type: object
+ description: Coordinates information
+ $ref: '#/definitions/RideCoordinates'
+ RideCoordinates:
+ type: object
+ description: Ride coordinates properties
+ properties:
+ pickup:
+ type: object
+ description: Pickup information
+ $ref: '#/definitions/Location'
+ dropoff:
+ type: object
+ description: Dropoff information
+ $ref: '#/definitions/Location'
+ location:
+ type: object
+ description: Location information
+ $ref: '#/definitions/Location'
+ destination:
+ type: object
+ description: Destination information
+ $ref: '#/definitions/Location'
+ Location:
+ type: object
+ description: Location property
+ properties:
+ lat:
+ type: number
+ format: float
+ description: Latitude
+ lng:
+ type: number
+ format: float
+ description: Longitude
+ address:
+ type: string
+ description: Address
+ time:
+ type: string
+ format: datetime
+ description: Time
+ RidePaginatedResponse:
+ type: object
+ description: Ride paginated response data
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Ride'
+ Provider:
+ type: object
+ description: Provide data
+ properties:
+ provider_uuid:
+ type: string
+ description: Provider unique ID
+ npi_id:
+ type: integer
+ description: National Provider ID
+ provider_name:
+ type: string
+ description: Provider name
+ address:
+ type: string
+ description: Provider Address
+ lat:
+ type: number
+ format: float
+ description: Latitude
+ lng:
+ type: number
+ format: float
+ description: Longitude
+ ProviderPaginatedResponse:
+ type: object
+ description: Provider paginated response data
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Provider'
+ RideType:
+ properties:
+ ride_type_uuid:
+ type: string
+ description: Internal UUID of the ride type
+ ride_type:
+ type: string
+ description: Internal type of the ride type
+ display_name:
+ type: string
+ description: Ride type
+ RideStatus:
+ properties:
+ ride_status_uuid:
+ type: string
+ description: Internal UUID of the ride status
+ ride_status:
+ type: string
+ description: Internal type of the ride status
+ display_name:
+ type: string
+ description: Ride type
+ RideTypeResponse:
+ type: array
+ description: List of the Ride Types
+ items:
+ $ref: '#/definitions/RideType'
+ RideETA:
+ properties:
+ ride_type_uuid:
+ type: string
+ description: Internal UUID of the ride type
+ ride_type:
+ type: string
+ description: Internal type of the ride type
+ display_name:
+ type: string
+ description: Ride type
+ eta_seconds:
+ type: number
+ description: ETA
+ RideETAResponse:
+ type: array
+ description: List of the Ride ETA's
+ items:
+ $ref: '#/definitions/RideETA'
+ RideDriver:
+ properties:
+ ride_type_uuid:
+ type: string
+ description: Internal UUID of the ride type
+ ride_type:
+ type: string
+ description: Internal type of the ride type
+ display_name:
+ type: string
+ description: Ride type
+ drivers:
+ type: array
+ description: Drivers location
+ items:
+ $ref: '#/definitions/Location'
+ RideDriverResponse:
+ type: array
+ description: List the Ride Drivers by type
+ items:
+ $ref: '#/definitions/RideDriver'
\ No newline at end of file
diff --git a/docs/swagger/nemt-portal-api_2.yaml b/docs/swagger/nemt-portal-api_2.yaml
new file mode 100644
index 0000000..cd34a9f
--- /dev/null
+++ b/docs/swagger/nemt-portal-api_2.yaml
@@ -0,0 +1,1244 @@
+swagger: "2.0"
+info:
+ version: "1.0.2"
+ title: NEMT Member API
+ description: |
+ RESTful API for NEMT Member App
+ Repo: nemt-portal-api
+ host: app.swaggerhub.com
+ contact:
+ name: Carlos Andrioli
+ email: carlos@brighterdevelopment.com
+basePath: /v1
+schemes:
+ - http
+consumes:
+ - application/json
+produces:
+ - application/json
+securityDefinitions:
+ AppKey:
+ type: apiKey
+ in: header
+ name: App
+ description: Application Key (use "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") only used to authenticate the application
+ AppToken:
+ type: apiKey
+ in: header
+ name: Token
+ description: The App Bearer token. Need to make a get request to the address "/v1/authenticate" with the "App" header and the log in body
+tags:
+ - name: auth
+ description: Endpoints for system and users authentication.
+ - name: member
+ description: Endpoints for members of a participating payer.
+ - name: visits
+ description: Endpoints for visits to participating providers by members of a participating payer.
+ - name: notifications
+ description: Endpoints for notifications related to members, visits, providers and system state.
+ - name: rides
+ description: Endpoints for rides to participating providers for members of participating payers.
+ - name: providers
+ description: Endpoints for participating providers related to a member of a participating payer
+ - name: messages
+ description: Endpoints for (tbd) message types.
+paths:
+ /authenticate/:
+ post:
+ tags:
+ - auth
+ summary: Authorize the application use
+ description: Authorizes the application routes returning a JWT token for authentication
+ operationId: authenticateApp
+ security:
+ - AppKey: []
+ parameters:
+ - name: data
+ in: body
+ description: Member authentication data
+ required: true
+ schema:
+ $ref: '#/definitions/AuthRequest'
+ responses:
+ 200:
+ description: Get the token for application authorization
+ schema:
+ $ref: '#/definitions/AuthResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/visits/:
+ get:
+ tags:
+ - visits
+ - member
+ summary: Get a filtered list of member-visits to participating providers
+ description: Get a list of visits
+ operationId: listVisits
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Visits paginated list
+ schema:
+ $ref: '#/definitions/VisitsPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ post:
+ tags:
+ - visits
+ - member
+ summary: Create a visit to a participating provider for an eligible member.
+ description: Reserves a pre-defined or arbitrary visit time range
+ operationId: addVisit
+ security:
+ - AppToken: []
+ parameters:
+ - name: data
+ in: body
+ description: Visit data
+ required: true
+ schema:
+ $ref: '#/definitions/Visit'
+ responses:
+ 200:
+ description: Visit object with all the ID and remanescent parameters filled
+ schema:
+ $ref: '#/definitions/Visit'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/visits/{visit_uuid}/:
+ get:
+ tags:
+ - visits
+ - member
+ summary: Get details of a single member-visit to a participating provider.
+ description: Get details of a single member-provider visit
+ operationId: getVisitDetail
+ security:
+ - AppToken: []
+ parameters:
+ - name: visit_uuid
+ in: path
+ description: Visit unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: Visit Details
+ schema:
+ $ref: '#/definitions/Visit'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ put:
+ tags:
+ - visits
+ - member
+ summary: Update a single member-visit to a participating provider.
+ description: Get the member visit
+ operationId: updatemember
+ security:
+ - AppToken: []
+ parameters:
+ - name: visit_uuid
+ in: path
+ description: Visit unique identifier
+ type: string
+ required: true
+ - name: data
+ in: body
+ description: Visit data
+ required: true
+ schema:
+ $ref: '#/definitions/Visit'
+ responses:
+ 200:
+ description: Visit detail
+ schema:
+ $ref: '#/definitions/Visit'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ delete:
+ tags:
+ - visits
+ - member
+ summary: Delete a single member-visit to a participating provider.
+ description: Cancel a member appointment
+ operationId: deletemember
+ security:
+ - AppToken: []
+ parameters:
+ - name: visit_uuid
+ in: path
+ description: Visit unique identifier
+ type: string
+ required: true
+ responses:
+ 204:
+ description: No return if everything works
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/members/:
+ get:
+ tags:
+ - member
+ summary: Get a filtered list of members
+ description: Get a list of members
+ operationId: listmembers
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: members paginated list
+ schema:
+ $ref: '#/definitions/MembersPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/members/{member_uuid}/:
+ get:
+ tags:
+ - member
+ summary: member detail
+ description: Get a member's detail data
+ operationId: getmemberDetail
+ security:
+ - AppToken: []
+ parameters:
+ - name: member_uuid
+ in: path
+ description: member unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: member detail
+ schema:
+ $ref: '#/definitions/Member'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/notifications/:
+ get:
+ tags:
+ - notifications
+ - member
+ summary: Get a list of notifications for a single member.
+ description: Get a list of notifications for a single member.
+ operationId: listNotifications
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Notification paginated list
+ schema:
+ $ref: '#/definitions/NotificationPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/notifications/{notification_uuid}/:
+ get:
+ tags:
+ - notifications
+ - member
+ summary: Get the member's notification
+ description: Get a specific notification
+ operationId: getNotification
+ security:
+ - AppToken: []
+ parameters:
+ - name: notification_uuid
+ in: path
+ description: Notification unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: Notification detail
+ schema:
+ $ref: '#/definitions/Notification'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/:
+ get:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Get a filtered list of rides for a single member.
+ description: Get a filtered list of rides for a single member.
+ operationId: listRides
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Rides paginated list
+ schema:
+ $ref: '#/definitions/RidePaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ post:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Create a ride to a participating provider for an eligible member.
+ description: Get the ride
+ operationId: addRide
+ security:
+ - AppToken: []
+ parameters:
+ - name: data
+ in: body
+ description: Book a scheduled ride with at least one ride_segment.
+ required: true
+ schema:
+ $ref: '#/definitions/RideRequest'
+ responses:
+ 200:
+ description: Ride object with all the ID and remanescent parameters filled
+ schema:
+ $ref: '#/definitions/Ride'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/{ride_uuid}/:
+ get:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Ride detail
+ description: Get a member's specific ride data
+ operationId: getRideDetail
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ responses:
+ 200:
+ description: Ride detail
+ schema:
+ $ref: '#/definitions/Ride'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ put:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Update a single member-ride
+ description: Update a single member-ride
+ operationId: updateRides
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ - name: data
+ in: body
+ description: Ride data
+ required: true
+ schema:
+ $ref: '#/definitions/Ride'
+ responses:
+ 200:
+ description: Ride detail
+ schema:
+ $ref: '#/definitions/Ride'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/{ride_uuid}/cancel:
+ post:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Cancel ride
+ description: Cancel a specific ride for a member
+ operationId: cancelRide
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ responses:
+ 204:
+ description: Empty response means that the cancel was aceppted
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rides/{ride_uuid}/destination:
+ put:
+ tags:
+ - rides
+ - visits
+ - member
+ summary: Change the ride destination
+ description: Change the ride destination
+ operationId: changeRideDestination
+ security:
+ - AppToken: []
+ parameters:
+ - name: ride_uuid
+ in: path
+ description: Ride unique identifier
+ type: string
+ required: true
+ - name: data
+ in: body
+ description: Destination data
+ required: true
+ schema:
+ $ref: '#/definitions/Location'
+ responses:
+ 200:
+ description: Location confirmation
+ schema:
+ $ref: '#/definitions/Location'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/ridetypes:
+ get:
+ tags:
+ - rides
+ security:
+ - AppToken: []
+ operationId: getRideTypes
+ summary: List the ride types
+ description: List the ride types from the database
+ parameters:
+ - name: lat
+ in: query
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: query
+ description: longitude
+ type: number
+ format: float
+ required: true
+ responses:
+ 200:
+ description: Ride Type list
+ schema:
+ $ref: '#/definitions/RideTypeResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/rideseta:
+ get:
+ tags:
+ - rides
+ security:
+ - AppToken: []
+ operationId: getRideEta
+ summary: Get the ETA of the Ride
+ description: Get the ETA of the types
+ parameters:
+ - name: lat
+ in: query
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: query
+ description: longitude
+ type: number
+ format: float
+ required: true
+ - name: dest_lat
+ in: query
+ description: destination latitude
+ type: number
+ format: float
+ required: true
+ - name: dest_lng
+ in: query
+ description: destination longitude
+ type: number
+ format: float
+ required: true
+ - name: ride_type_uuid
+ in: query
+ description: ride type UUID
+ type: string
+ responses:
+ 200:
+ description: Ride ETA list
+ schema:
+ $ref: '#/definitions/RideETAResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/ridedrivers:
+ get:
+ tags:
+ - rides
+ security:
+ - AppToken: []
+ operationId: getRideDrivers
+ summary: Get Drivers near origin location.
+ description: Get Drivers close to the Origin location
+ parameters:
+ - name: lat
+ in: query
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: query
+ description: longitude
+ type: number
+ format: float
+ required: true
+ - name: ride_type_uuid
+ in: query
+ description: ride type UUID
+ type: string
+ responses:
+ 200:
+ description: Ride Drivers list
+ schema:
+ $ref: '#/definitions/RideDriverResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/providers/:
+ get:
+ tags:
+ - rides
+ - providers
+ - member
+ summary: Get providers
+ description: Get a list of providers
+ operationId: getProviders
+ security:
+ - AppToken: []
+ parameters:
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Provider list
+ schema:
+ $ref: '#/definitions/ProviderPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ /nemt/providers/{lat}/{lng}/:
+ get:
+ tags:
+ - rides
+ - providers
+ - member
+ summary: Provider by Location
+ description: Get a list of providers for a current location
+ operationId: getProvidersByLocation
+ security:
+ - AppToken: []
+ parameters:
+ - name: lat
+ in: path
+ description: latitude
+ type: number
+ format: float
+ required: true
+ - name: lng
+ in: path
+ description: longitude
+ type: number
+ format: float
+ required: true
+ - name: page
+ in: query
+ description: Pagination page number
+ default: 1
+ required: false
+ type: integer
+ format: int64
+ - name: quantity
+ in: query
+ description: Pagination quantity per page
+ default: 10
+ type: integer
+ format: int64
+ responses:
+ 200:
+ description: Provider list
+ schema:
+ $ref: '#/definitions/ProviderPaginatedResponse'
+ 401:
+ description: Unauthorized access
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 422:
+ description: Validation error
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+ 503:
+ description: Service Unavailable
+ schema:
+ $ref: '#/definitions/DefaultErrorResponse'
+definitions:
+ DefaultErrorResponse:
+ type: object
+ description: Default error response data
+ properties:
+ error:
+ type: boolean
+ description: Indicates if the response is an error
+ message:
+ type: string
+ description: Detailed response message
+ AuthRequest:
+ type: object
+ description: Request from application authrization
+ properties:
+ email:
+ type: string
+ description: Member e-mail
+ password:
+ type: string
+ description: Base64 encoded password
+ AuthResponse:
+ type: object
+ description: Response from application authrization
+ properties:
+ token:
+ type: string
+ description: The token string for app authorization
+ valid_time:
+ type: integer
+ format: int64
+ description: Token expiration time in Unix time format
+ server_time:
+ type: integer
+ format: int64
+ description: Server time in Unix time format
+ PaginatedResponse:
+ type: object
+ description: Paginated response data
+ properties:
+ pagination:
+ type: object
+ description: Pagination data
+ properties:
+ total_records:
+ type: integer
+ format: int64
+ description: Total result count
+ records_per_page:
+ type: integer
+ format: int64
+ description: Max records per page
+ total_pages:
+ type: integer
+ format: int64
+ description: Total page count
+ current_page:
+ type: integer
+ format: int64
+ description: Current page number
+ data:
+ type: array
+ items:
+ type: object
+ description: Paginaged data
+ Member:
+ type: object
+ description: member data
+ properties:
+ member_uuid:
+ type: string
+ description: member unique ID
+ name:
+ type: string
+ description: Name
+ phone_number:
+ type: string
+ description: Phone number
+ MembersPaginatedResponse:
+ type: object
+ description: members paginated response data
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Member'
+ Driver:
+ type: object
+ description: Driver data
+ properties:
+ driver_uuid:
+ type: string
+ description: Driver unique ID
+ name:
+ type: string
+ description: Full Name (?)
+ phone_number:
+ type: string
+ description: Vehicle Brand
+ model:
+ type: string
+ description: Vehicle Model
+ plate:
+ type: string
+ description: Vehicle Plate
+ color:
+ type: string
+ description: Vehicle Color
+ Visit:
+ type: object
+ description: Details of a member-visit to a participating proivider.
+ properties:
+ visit_uuid:
+ type: string
+ description: Unique Visit ID
+ VisitsPaginatedResponse:
+ type: object
+ description: Paginated list of Visits.
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Visit'
+ Notification:
+ type: object
+ description: Notification data
+ properties:
+ notification_uuid:
+ type: string
+ description: Notification unique ID
+ notification:
+ type: string
+ description: Notification message
+ is_read:
+ type: boolean
+ description: Verify if the message was read
+ NotificationPaginatedResponse:
+ type: object
+ description: Notification paginated response data
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Notification'
+ RideRequest:
+ type: object
+ description: Request a scheduled ride with at least one ride_segment.
+ properties:
+ ride_type:
+ type: object
+ description: Ride Type. For on-demand requests, Dispatch supports lyft, lyft_plus, lyft_premier, lyft_lux, and lyft_luxsuv. For scheduled rides Dispatch only supports lyft type rides.
+ $ref: '#/definitions/RideType'
+ visit_uuid:
+ type: string
+ description: Unique Visit ID.
+ origin:
+ type: object
+ description: Scheduled starting location of ride segment.
+ $ref: '#/definitions/Location'
+ destination:
+ type: object
+ description: Ending location of ride segment.
+ $ref: '#/definitions/Location'
+ scheduled_pickup_range:
+ type: object
+ description: Scheduled time for Pickup.
+ $ref: '#/definitions/scheduled_pickup_range'
+ Ride:
+ type: object
+ description: Information about a single ride for a member of a participating payer to a participating provider.
+ properties:
+ ride_uuid:
+ type: string
+ description: Unique Ride ID.
+ ride_type:
+ type: object
+ description: Ride Type. For on-demand requests, Dispatch supports lyft, lyft_plus, lyft_premier, lyft_lux, and lyft_luxsuv. Ride Types; for scheduled rides Dispatch only supports lyft rides.
+ $ref: '#/definitions/RideType'
+ ride_status:
+ type: object
+ description: Ride Status.
+ $ref: '#/definitions/RideStatus'
+ requested:
+ type: string
+ format: datetime
+ description: Request Date.
+ driver:
+ type: object
+ description: Driver information.
+ $ref: '#/definitions/Driver'
+ locations:
+ type: object
+ description: Location information.
+ $ref: '#/definitions/locations'
+
+
+
+ locations:
+ type: object
+ description: Ride location properties.
+ properties:
+ origin:
+ type: object
+ description: Starting location of ride segment.
+ $ref: '#/definitions/Location'
+ dropoff:
+ type: object
+ description: Actual Dropoff locationof ride segment.
+ $ref: '#/definitions/Location'
+ currentLocation:
+ type: object
+ description: Current or last known actual location of vehicle.
+ $ref: '#/definitions/Location'
+ destination:
+ type: object
+ description: Ending location of ride segment.
+ $ref: '#/definitions/Location'
+
+ scheduled_pickup_range:
+ type: object
+ description: Object that must be included for scheduled rides. Optional otherwise. Follows Lyft conventions. Returned only for Scheduled Rides.
+ properties:
+ scheduled_pickup_range.timestamp_ms:
+ type: number
+ format: float
+ description: Date and time of the pickup in milliseconds.
+ enum: [600000]
+ scheduled_pickup_range.range_ms:
+ type: number
+ format: int
+ description: Range of the pickup time in milliseconds.
+ enum: [1472558400000]
+ Location:
+ type: object
+ description: Actual reported location of vehicle at time of report (versus scheduled origin, destination, etc.)
+ properties:
+ lat:
+ type: number
+ format: float
+ description: Latitude
+ enum: [37.795546]
+ lng:
+ type: number
+ format: float
+ description: Longitude
+ enum: [-122.393420]
+ address:
+ type: string
+ description: Full Address as single line.
+ enum: [568 Brannan St, San Francisco, CA 94107, USA]
+ eta:
+ type: number
+ format: float
+ description: Estimated time is seconds until vehicle arrival.
+ enum: [3600]
+ RidePaginatedResponse:
+ type: object
+ description: Paginated list of Rides.
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Ride'
+ Provider:
+ type: object
+ description: Provide data
+ properties:
+ provider_uuid:
+ type: string
+ description: Unique Provider ID
+ npi_id:
+ type: integer
+ description: National Provider ID
+ provider_name:
+ type: string
+ description: Provider Name
+ address:
+ type: string
+ description: Provider Address
+ lat:
+ type: number
+ format: float
+ description: Latitude
+ lng:
+ type: number
+ format: float
+ description: Longitude
+ ProviderPaginatedResponse:
+ type: object
+ description: Paginated list of Providers
+ allOf:
+ - $ref: '#/definitions/PaginatedResponse'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/Provider'
+ RideType:
+ type: object
+ description: Object containing detailed info on type of the TNC ride.
+ properties:
+ ride_type_uuid:
+ type: string
+ description: Internal UUID of the ride type.
+ ride_type:
+ type: string
+ enum: [lyft, lyft_line,lyft_plus,lyft_premier.lyft_lux,lyft_luxsuv]
+ description: Internal type of the ride. For on-demand requests, Dispatch supports lyft, lyft_plus, lyft_premier, lyft_lux, and lyft_luxsuv. Ride Types; for scheduled rides Dispatch only supports lyft rides.
+ display_name:
+ type: string
+ description: User-facing description of a TNC Ride type.
+ enum: [Lyft, Lyft Line,Lyft Plus,Lyft Premier, Lyft Lux,Lyft Luxsuv]
+ image_url:
+ type: string
+ description: Full URL of icon for ride type for display on map, etc.
+ enum: [https://cdn.lyft.com/assets/Vehicle_plus.png]
+ RideStatus:
+ properties:
+ ride_status_uuid:
+ type: string
+ description: UUID of the ride status entry.
+ ride_status:
+ type: string
+ description: Internal description of ride status.
+ enum: [pending,accepted,arrived,pickedUp,droppedOff,
+ canceled,failed]
+ display_name:
+ type: string
+ description: User-facing description Ride Status
+ enum: [Pending,Accepted,Arrived,Picked Up,Dropped Off,
+ Canceled,Failed]
+ status_description:
+ type: string
+ description: User-facing description of Ride Status.
+ enum: [A passenger's ride request has been made and Lyft is matching the passenger to a driver., A driver has accepted the ride., The driver has arrived at the pickup location.,The driver has picked up the passenger.,The driver has dropped off the passenger.,
+ The ride has been canceled. In this ride state the additional field canceled_by indicates whether the ride was canceled by the driver passenger or no_drivers_available if no driver could be found for the ride.,Unknown system error occurred. Exceptionally rare.]
+ RideTypeResponse:
+ type: array
+ description: List of the Ride Types
+ items:
+ $ref: '#/definitions/RideType'
+ RideETA:
+ properties:
+ ride_type_uuid:
+ type: string
+ description: Internal UUID of the ride type
+ ride_type:
+ type: string
+ enum: [lyft, lyft_line,lyft_plus,lyft_premier.lyft_lux,lyft_luxsuv]
+ description: Internal type of the ride. For on-demand requests, Dispatch supports lyft, lyft_plus, lyft_premier, lyft_lux, and lyft_luxsuv. Ride Types; for scheduled rides Dispatch only supports lyft rides.]
+ display_name:
+ type: string
+ description: Ride Type
+ eta_seconds:
+ type: number
+ description: Estimated seconds remaining until pickup from origin
+ enum: [360]
+ RideETAResponse:
+ type: array
+ description: List of the Ride ETA's
+ items:
+ $ref: '#/definitions/RideETA'
+ RideDriver:
+ properties:
+ ride_type_uuid:
+ type: string
+ description: Internal UUID of the ride type
+ ride_type:
+ type: string
+ description: Service of the TNC ride.
+ display_name:
+ type: string
+ description: Ride Type
+ drivers:
+ type: array
+ description: Drivers' locations
+ items:
+ $ref: '#/definitions/Location'
+ RideDriverResponse:
+ type: array
+ description: List Drivers by type
+ items:
+ $ref: '#/definitions/RideDriver'
\ No newline at end of file
diff --git a/docs/wiki/01 - Definitions.md b/docs/wiki/01 - Definitions.md
new file mode 100644
index 0000000..4e84dc5
--- /dev/null
+++ b/docs/wiki/01 - Definitions.md
@@ -0,0 +1,13 @@
+# Definitions
+
+## Steps
+
+- `build`: compilation and project preparation step
+- `run`: execution step
+
+## Environments
+
+- `loc`: local
+- `dev`: development
+- `stg`: staging
+- `prd`: production
diff --git a/docs/wiki/02 - Environments.md b/docs/wiki/02 - Environments.md
new file mode 100644
index 0000000..905192d
--- /dev/null
+++ b/docs/wiki/02 - Environments.md
@@ -0,0 +1,21 @@
+# Environments
+
+## Definitions
+
+- Local (`loc`)
+
+Your local machine.
+
+- Development (`dev`)
+
+Useful for us to test the implementation without messing with
+the partners experience.
+
+- Staging (`stg`)
+
+Used to simulate production and as homologation version.
+Works as the last step before production.
+
+- Production (`prd`)
+
+Production server.
diff --git a/docs/wiki/03 - Folders.md b/docs/wiki/03 - Folders.md
new file mode 100644
index 0000000..684aefa
--- /dev/null
+++ b/docs/wiki/03 - Folders.md
@@ -0,0 +1,64 @@
+# Folders
+
+## Reason
+
+The goals for a common project's folder structure is to mantain the organization
+and to promote a common language between the programmers, decreasing the new
+members' learning curve.
+
+## Definitions
+
+### Structure
+
+- `domain`:
+
+ - `service`:
+ contains the business logic and persistence, i.e. validating values based on business
+ rules
+
+ - `contract`:
+ contains the interfaces for the whole app; useful for mocking dependencies on
+ the tests and also decoupling the packages from each other, making the code independent
+ from external technologies, e.g. databases
+
+ - `entity`:
+ represents the values our domain understands
+
+- `infra`:
+ contains utilities that will be used across the whole app
+
+- `data`:
+ contains the connection with the database or any other way to do the persistence
+
+ - `data*`:
+ an "implementation"
+
+- `application`:
+ represents our application as a whole
+
+ - `applicationservice`:
+ contains the application logic, i.e. parses and validates the data received, calls
+ many domain's services, parses the output data and sends it
+
+ - `entitymapping`:
+ contains the functions that parses the application's view model to the domain's
+ entities, and vice-versa
+
+ - `viewmodel`:
+ the data that will be sent and received from the app; it differs from the entity
+ because it does not represent the values of our app, but rather the values the
+ front-end server will understand
+
+- `server`:
+ contains the definitions for the web server
+
+ - `router`:
+ defines the routes and its handlers; contains no logic, only calls the application
+ package
+
+ - `serverconfig`:
+ defines the middlewares and the server's configurations
+
+- `static`:
+ not required; mostly used for static files, such as large texts, email templates,
+ static values, etc, or temporary files (commonly in `static/temp`)
diff --git a/docs/wiki/04 - Dockerfile.md b/docs/wiki/04 - Dockerfile.md
new file mode 100644
index 0000000..1200b6e
--- /dev/null
+++ b/docs/wiki/04 - Dockerfile.md
@@ -0,0 +1,31 @@
+# Dockerfile
+
+## Definitions
+
+There are two `Dockerfile`s, one for each step of execution set in
+the [definitions document][definitions-doc].
+
+## Containers
+
+- Build
+
+Defined in `Dockerfile.build`
+
+Has installed every program that is needed to build the code.
+Gets the source, install the dependencies and makes the final binary
+of our app.
+
+The reason for us to have a container just for the building process is
+that it demands lots of programs and dependencies to set up the Go
+environment and build everything, which aren't needed in the server for
+our app to run. Without it, the container for the running process would
+be huge, full of useless binaries and softwares.
+
+- Run
+
+Defined in `Dockerfile.run`
+
+This is the container that will run in the servers. Contains nothing,
+but our app and what it need to make it run.
+
+[definitions-doc]: https://bitbucket.org/nemt/nemt-portal-api/blob/master/docs/wiki/01%20-%20Definitions.md
\ No newline at end of file
diff --git a/docs/wiki/05 - Makefile.md b/docs/wiki/05 - Makefile.md
new file mode 100644
index 0000000..6297702
--- /dev/null
+++ b/docs/wiki/05 - Makefile.md
@@ -0,0 +1,67 @@
+# Makefile
+
+## Reason
+
+Great to simplify and standardize commons and repetitive tasks.
+
+## Definitions
+
+Following the patterns of the [definitions document][definitions-doc], every task related to
+the compilation os preparation of the server for execution will `build` as part of the name,
+while tasks related to the execution itself will be call `run`.
+
+## Common instructions
+
+### Build
+
+- `create-build-container`: creates the container for building, using `Dockerfile.build`
+
+- `build`: build the server inside the container and gets the binary
+
+- `build-loc`: calls `build` using local (`loc`) environment
+
+- `build-dev`: calls `build` using development (`dev`) environment
+
+- `build-stg`: calls `build` using staging (`stg`) environment
+
+- `build-prd`: calls `build` using production (`prd`) environment
+
+### Run
+
+- `create-run-container`: creates the container for execution, using `Dockerfile.run`
+
+- `run`: executes the app inside the container
+
+- `run-loc`: calls `run` using local (`loc`) environment
+
+- `run-dev`: calls `run` using development (`dev`) environment
+
+- `run-stg`: calls `run` using staging (`stg`) environment
+
+- `run-prd`: calls `run` using production (`prd`) environment
+
+- `run-host`: executes the app without a container, directly on the local host
+
+### Environment
+
+- `set-loc`: defines the environment as "local" (`loc`)
+
+- `set-dev`: defines the environment as "development" (`dev`)
+
+- `set-stg`: defines the environment as "staging" (`stg`)
+
+- `set-prd`: defines the environment as "production" (`prd`)
+
+### Database
+
+- `migrate`: executes the full migration of the database
+
+### Tests
+
+- `test`: executes the whole battery of tests
+
+### Others
+
+- `clean`: remove binaries and compiled files
+
+[definitions-doc]: https://bitbucket.org/nemt/nemt-portal-api/blob/master/docs/wiki/01%20-%20Definitions.md
\ No newline at end of file
diff --git a/domain/constants.go b/domain/constants.go
new file mode 100644
index 0000000..5420d1f
--- /dev/null
+++ b/domain/constants.go
@@ -0,0 +1,15 @@
+package domain
+
+type errorString string
+
+func (err errorString) Error() string {
+ return string(err)
+}
+
+// ErrCacheMiss indicates a cache miss when fetching an item from CacheManager.
+const ErrCacheMiss = errorString("cache miss: key not found")
+
+// Used to log errors with communication and operation of cache implementation
+const LogProblemGettingFromCache = "Getting from cache is not working correctly: %v"
+const LogProblemPuttingToCache = "Putting to cache is not working correctly: %v"
+const LogProblemExpiringCache = "Expiring cache key is not working correctly: %v"
diff --git a/domain/contract/cache.go b/domain/contract/cache.go
new file mode 100644
index 0000000..f8688d8
--- /dev/null
+++ b/domain/contract/cache.go
@@ -0,0 +1,19 @@
+package contract
+
+import "time"
+
+// CacheManager defines the main caching interface
+// - Get methods can return domain.ErrCacheMiss
+type CacheManager interface {
+ GetItem(key string) ([]byte, error)
+ SetItem(key string, data []byte) error
+
+ GetString(key string) (string, error)
+ SetString(key string, data string) error
+
+ GetStruct(key string, data interface{}) error
+ SetStruct(key string, data interface{}) error
+
+ GetExpiration(key string) (time.Duration, error)
+ SetExpiration(key string, expiration time.Duration) error
+}
diff --git a/domain/contract/data.go b/domain/contract/data.go
new file mode 100644
index 0000000..6489412
--- /dev/null
+++ b/domain/contract/data.go
@@ -0,0 +1,16 @@
+package contract
+
+// DataManager holds the methods that manipulates the main data.
+type DataManager interface {
+ repoManager
+ Begin() (TransactionManager, error)
+ Close() error
+}
+
+// TransactionManager holds the methods that manipulates the main
+// data, from within a transaction.
+type TransactionManager interface {
+ repoManager
+ Rollback() error
+ Commit() error
+}
diff --git a/domain/contract/repo.go b/domain/contract/repo.go
new file mode 100644
index 0000000..d2196e8
--- /dev/null
+++ b/domain/contract/repo.go
@@ -0,0 +1,104 @@
+package contract
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+type repoManager interface {
+ Users() UserRepo
+ Rides() RideRepo
+ Visits() VisitRepo
+ Provider() ProviderRepo
+ Notification() NotificationRepo
+ Profile() ProfileRepo
+ Organization() OrganizationRepo
+}
+
+// UserRepo defines the data set for users
+type UserRepo interface {
+ GetAll() (list []entity.User, err error)
+ GetByID(userID int64) (retVal entity.User, err error)
+ GetByUUID(uuid string, profile string) (entity.User, error)
+ Login(email string, pass string) (entity.User, error)
+ FullLogin(loginType string, key string, pass string, profile string) (entity.User, error)
+ Create(user entity.User) (entity.User, error)
+ GetUsersByProfile(profile string) ([]entity.User, error)
+ SaveAddress(address entity.Address) (entity.Address, error)
+ GetAddressByUUID(addressUUID string) (entity.Address, error)
+ GetContactType() (retVal []entity.ContactType, err error)
+ RemoveAddress(addressUUID string) error
+}
+
+// RideRepo defines the data set for Rides
+type RideRepo interface {
+ Save(ride entity.Ride) (entity.Ride, error)
+ GetAll(user entity.User) ([]entity.Ride, error)
+ GetByID(id int64, user entity.User) (entity.Ride, error)
+ GetByUUID(uuid string, user entity.User) (entity.Ride, error)
+ GetByInternalID(internalID string) (entity.Ride, error)
+ GetByUserID(userID int64, user entity.User) ([]entity.Ride, error)
+ GetByUserUUID(userUUID string, user entity.User) ([]entity.Ride, error)
+ GetByUUIDAndUserUUID(UUID string, userUUID string) (entity.Ride, error)
+ UpdateStatus(rideUUID string, status string) error
+ Update(hook entity.WebhookResponse, user entity.User) (entity.Ride, error)
+ GetLastRideByPhoneNumber(phoneNumber string) (entity.Ride, error)
+ GetLastRideByDriversNumber(phoneNumber string) (entity.Ride, error)
+ GetByInternalPassengerID(internalPassengerID string) (entity.Ride, error)
+ GetByVisitUUID(visitUUID string, user entity.User) ([]entity.Ride, error)
+ GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user entity.User) (entity.Ride, error)
+}
+
+// ProviderRepo defines the data set for Provider
+type ProviderRepo interface {
+ Save(providers []entity.ProviderResponse, user entity.User) ([]entity.Provider, error)
+ GetAll(user entity.User) ([]entity.Provider, error)
+ Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user entity.User) ([]entity.Provider, error)
+ GetByMukID(mukID string, user entity.User) (entity.Provider, error)
+}
+
+// NotificationRepo defines the data set for Notification
+type NotificationRepo interface {
+ Create(notification entity.Notification) (entity.Notification, error)
+ GetByUserUUIDAndReadStatus(userUUID string, status string, isRead bool) ([]entity.Notification, error)
+ GetByUserUUID(userUUID string, status string) ([]entity.Notification, error)
+ ReadStatus(notificationUUID string, readed bool) error
+ GetLastNotificationFromPhoneNumber(notificationType string, phoneNumber string, status string) (entity.Notification, error)
+}
+
+// ProviderRepo defines the data set for Rides
+type OrganizationRepo interface {
+ GetAllTypes() ([]entity.OrganizationType, error)
+ GetByType(organizationTypeKey string) ([]entity.Organization, error)
+ GetByUUID(organizationUUID string) (entity.Organization, error)
+ GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error)
+ GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error)
+ GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error)
+ GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error)
+ GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error)
+ GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error)
+ GetByID(organizationID int64) (entity.Organization, error)
+ GetChildsByID(organizationID int64) ([]entity.Organization, error)
+ GetByName(name string, searchType string) ([]entity.Organization, error)
+ SetParentOrganization(organizationID int64, parentOrganizationID int64) error
+ InactivateOrganizationAddress(address entity.OrganizationAddress) error
+ SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error)
+ InactivateOrganizationContact(contact entity.OrganizationContact) error
+ SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error)
+ AddOrganization(organization entity.Organization) (entity.Organization, error)
+ GetTypeByKey(key string) (entity.OrganizationType, error)
+}
+
+// VisitRepo defines the data set for Rides
+type VisitRepo interface {
+ Create(visit entity.Visit) (entity.Visit, error)
+ GetAll(user entity.User) ([]entity.Visit, error)
+ GetByUUID(visitUUID string, user entity.User) (entity.Visit, error)
+ GetByID(visitID int64, user entity.User) (entity.Visit, error)
+}
+
+type ProfileRepo interface {
+ GetAll() ([]entity.Profile, error)
+ GetByKey(key string) (entity.Profile, error)
+ GetVisibles(visible bool) ([]entity.Profile, error)
+ GetByOrganizationType(organizationTypeID int64) ([]entity.Profile, error)
+}
diff --git a/domain/contract/tnc.go b/domain/contract/tnc.go
new file mode 100644
index 0000000..1724677
--- /dev/null
+++ b/domain/contract/tnc.go
@@ -0,0 +1,12 @@
+package contract
+
+type tncManager interface {
+ TNC() TNCManager
+}
+
+//TNCManager defines the integration with any TNC
+type TNCManager interface {
+ GetETA(lag float64, log float64, params map[string]interface{}) (interface{}, error)
+ GetDrivers(lag float64, log float64) (interface{}, error)
+ GetTypes(lag float64, log float64, params map[string]interface{}) (interface{}, error)
+}
diff --git a/domain/entity/address.go b/domain/entity/address.go
new file mode 100644
index 0000000..5dfae63
--- /dev/null
+++ b/domain/entity/address.go
@@ -0,0 +1,21 @@
+package entity
+
+type Address struct {
+ ID int64
+ UUID string
+ InternalID string
+ Name string
+ Address string
+ AddressType Params
+ Latitude float64
+ Longitude float64
+ Origin Params
+ User User
+ CreatedUser User
+}
+
+type Params struct {
+ ID int64
+ Key string
+ Name string
+}
diff --git a/domain/entity/eligibility.go b/domain/entity/eligibility.go
new file mode 100644
index 0000000..642d255
--- /dev/null
+++ b/domain/entity/eligibility.go
@@ -0,0 +1,252 @@
+package entity
+
+type Interchange struct {
+ ISA ISA
+ Division Division
+}
+
+type ISA struct {
+ ISA01 string
+ ISA02 string
+ ISA03 string
+ ISA04 string
+ ISA05 string
+ ISA06 string
+ ISA07 string
+ ISA08 string
+ ISA09 string
+ ISA10 string
+ ISA11 string
+ ISA12 string
+ ISA13 string
+ ISA14 string
+ ISA15 string
+ ISA16 string
+}
+
+type Division struct {
+ GS GS
+ HealthCareEligibilityBenefitResponse HealthCareEligibilityBenefitResponse
+}
+
+type GS struct {
+ GS01 string
+ GS02 string
+ GS03 string
+ GS04 string
+ GS05 string
+ GS06 string
+ GS07 string
+ GS08 string
+}
+
+type HealthCareEligibilityBenefitResponse struct {
+ ST0010 ST0010
+ BHT0020 BHT0020
+ LoopHL0030 LoopHL0030
+}
+
+type ST0010 struct {
+ ST01 string
+ ST02 string
+ ST03 string
+}
+
+type BHT0020 struct {
+ BHT01 string
+ BHT02 string
+ BHT03 string
+ BHT04 string
+ BHT05 string
+}
+
+type LoopHL0030 struct {
+ HL0030 HL0030
+ LoopNM10060 LoopNM10060
+ LoopHL0460 LoopHL0460
+}
+
+type HL0030 struct {
+ HL01 string
+ HL02 string
+ HL03 string
+ HL04 string
+}
+
+type LoopNM10060 struct {
+ NM10060 NM10060
+}
+
+type NM10060 struct {
+ NM101 string
+ NM102 string
+ NM103 string
+ NM104 string
+ NM105 string
+ NM106 string
+ NM107 string
+ NM108 string
+ NM109 string
+}
+
+type LoopHL0460 struct {
+ HL0460 HL0460
+ LoopNM10490 LoopNM10490
+ LoopHL0890 LoopHL0890
+}
+
+type HL0460 struct {
+ HL01 string
+ HL02 string
+ HL03 string
+ HL04 string
+}
+
+type LoopNM10490 struct {
+ NM10490 NM10490
+}
+
+type NM10490 struct {
+ NM101 string
+ NM102 string
+ NM103 string
+ NM104 string
+ NM105 string
+ NM106 string
+ NM107 string
+ NM108 string
+ NM109 string
+}
+
+type LoopHL0890 struct {
+ HL0890 HL0890
+ TRN0900 TRN0900
+ LoopNM10920 LoopNM10920
+}
+
+type HL0890 struct {
+ HL01 string
+ HL02 string
+ HL03 string
+ HL04 string
+}
+
+type TRN0900 struct {
+ TRN01 string
+ TRN02 string
+ TRN03 string
+}
+
+type LoopNM10920 struct {
+ NM10920 NM10920
+ REF0930 REF0930
+ N30950 N30950
+ N40960 N40960
+ DMG1000 DMG1000
+ DTP1030 DTP1030
+ LoopEB1050 []LoopEB1050
+}
+
+type NM10920 struct {
+ NM101 string
+ NM102 string
+ NM103 string
+ NM104 string
+ NM105 string
+ NM106 string
+ NM107 string
+ NM108 string
+ NM109 string
+}
+
+type REF0930 struct {
+ REF01 string
+ REF02 string
+ REF03 string
+}
+
+type N30950 struct {
+ N301 string
+}
+
+type N40960 struct {
+ N401 string
+ N402 string
+ N403 string
+}
+
+type DMG1000 struct {
+ DMG01 string
+ DMG02 string
+ DMG03 string
+}
+
+type DTP1030 struct {
+ DTP01 string
+ DTP02 string
+ DTP03 string
+}
+
+type LoopEB1050 struct {
+ EB1050 EB1050
+ REF1070 REF1070
+ MSG1180 MSG1180
+ LoopIII1190 LoopIII1190
+ LS1260 LS1260
+ LoopNM11270 LoopNM11270
+}
+
+type EB1050 struct {
+ EB01 string
+ EB02 string
+ EB03 string
+ EB04 string
+ EB05 string
+ EB06 string
+ EB07 string
+ EB08 string
+ EB09 string
+ EB10 string
+ EB11 string
+ EB12 string
+}
+
+type REF1070 struct {
+ REF01 string
+ REF02 string
+ REF03 string
+}
+
+type MSG1180 struct {
+ MSG01 string
+}
+
+type LS1260 struct {
+ LS01 string
+}
+
+type LoopIII1190 struct {
+ III1190 III1190
+}
+
+type III1190 struct {
+ III01 string
+ III02 string
+}
+
+type LoopNM11270 struct {
+ NM11270 NM11270
+ PER1310 PER1310
+}
+
+type NM11270 struct {
+ NM101 string
+ NM102 string
+ NM103 string
+}
+
+type PER1310 struct {
+ PER01 string
+ PER02 string
+ PER03 string
+}
diff --git a/domain/entity/notification.go b/domain/entity/notification.go
new file mode 100644
index 0000000..7600f40
--- /dev/null
+++ b/domain/entity/notification.go
@@ -0,0 +1,20 @@
+package entity
+
+import "time"
+
+type Notification struct {
+ ID int64 `json:"-"`
+ UUID string `json:"uuid"`
+ From string `json:"to"`
+ To string `json:"to"`
+ Type string `json:"type"`
+ TypeID int64 `json:"type_id"`
+ Subject string `json:"subject"`
+ Message string `json:"message"`
+ MessageType string `json:"message_type"`
+ Ride Ride `json:"ride"`
+ User User `json:"user"`
+ CreatedUser User `json:"created_user"`
+ Created time.Time `json:"create_at"`
+ Read bool `json:"read"`
+}
diff --git a/domain/entity/organization.go b/domain/entity/organization.go
new file mode 100644
index 0000000..5b7af8b
--- /dev/null
+++ b/domain/entity/organization.go
@@ -0,0 +1,68 @@
+package entity
+
+import (
+ "time"
+)
+
+type OrganizationType struct {
+ ID int64 `json:"-"`
+ Name string `json:"name"`
+ Key string `json:"key"`
+ Description string `json:"desc"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
+}
+
+type Organization struct {
+ ID int64 `json:"-"`
+ UUID string `json:"id"`
+ Type OrganizationType `json:"type"`
+ Name string `json:"name"`
+ Description string `json:"desc"`
+ ReferenceID int64 `json:"-"`
+ ParentID int64 `json:"-"`
+ Main bool `json:"main"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
+ Active bool `json:"active"`
+ Blocked bool `json:"blocked"`
+ Suspended bool `json:"suspended"`
+ Author User `json:"author"`
+ LastEditor User `json:"last_editor"`
+ Contacts []OrganizationContact `json:"contacts"`
+ Addresses []OrganizationAddress `json:"addresses"`
+ ChildOrgs []Organization `json:"childs"`
+ Parent *Organization `json:"parent"`
+}
+
+type OrganizationContact struct {
+ ID int64 `json:"-"`
+ UUID string `json:"id"`
+ Organization *Organization `json:"organization"`
+ Type ContactType `json:"type"`
+ Contact string `json:"contact"`
+ Name string `json:"name"`
+ Description string `json:"desc"`
+ Created time.Time `json:"created"`
+ CreatedUser User `json:"author"`
+ Updated time.Time `json:"updated"`
+ UpdatedUser User `json:"last_editor"`
+ Active bool `json:"active"`
+}
+
+type OrganizationAddress struct {
+ ID int64 `json:"-"`
+ UUID string `json:"id"`
+ Organization *Organization `json:"organization"`
+ InternalID string `json:"internal_id"`
+ Name string `json:"name"`
+ Address string `json:"address"`
+ Description string `json:"desc"`
+ Latitude float64 `json:"lat"`
+ Longitude float64 `json:"long"`
+ Created time.Time `json:"created"`
+ CreatedUser User `json:"author"`
+ Updated time.Time `json:"updated"`
+ UpdatedUser User `json:"last_editor"`
+ Active bool `json:"active"`
+}
diff --git a/domain/entity/profile.go b/domain/entity/profile.go
new file mode 100644
index 0000000..8f0ac88
--- /dev/null
+++ b/domain/entity/profile.go
@@ -0,0 +1,17 @@
+package entity
+
+import "time"
+
+type Profile struct {
+ ID int64 `json:"-"`
+ Name string `json:"name"`
+ Key string `json:"key"`
+ Description string `json:"desc"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
+ Active bool `json:"active"`
+ Blocked bool `json:"blocked"`
+ Suspended bool `json:"suspended"`
+ Visible bool `json:"visible"`
+ Organization Organization `json:"organization"`
+}
diff --git a/domain/entity/provider.go b/domain/entity/provider.go
new file mode 100644
index 0000000..1f3be21
--- /dev/null
+++ b/domain/entity/provider.go
@@ -0,0 +1,126 @@
+package entity
+
+import (
+ "time"
+)
+
+type Provider struct {
+ ProviderID int64 `json:"-"`
+ ProviderUUID string `json:"provider_uuid"`
+ InternalID string `json:"internal_id"`
+ InternalSuffixID string `json:"internal_suffix_id"`
+ MukID string `json:"muk_id"`
+ OrganizatioName string `json:"org_name"`
+ Gender string `json:"gender"`
+ AcceptNewPatients string `json:"accept_new_patients"`
+ Name string `json:"name"`
+ FirstName string `json:"first"`
+ MiddleName string `json:"middle"`
+ LastName string `json:"last"`
+ Title string `json:"title"`
+ Active bool `json:"active"`
+ Enabled bool `json:"enabled"`
+ CreateDate time.Time `json:"create_at"`
+ UpdateDate time.Time `json:"update_at"`
+ CreatedUser User `json:"created_user"`
+ Keys []ProviderKey `json:"keys"`
+ Address ProviderAddress `json:"address"`
+ Distance float64 `json:"distance"`
+}
+
+type ProviderKey struct {
+ ProviderKeyID int64 `json:"-"`
+ Provider Provider `json:"provider"`
+ InternalID string `json:"internal_id"`
+ InternalSuffixID string `json:"internal_suffix_id"`
+ LocationSeqNumber string `json:"location_seq_number"`
+ PlanCode string `json:"plan_code"`
+ ProductID string `json:"product_id"`
+ TreatmentCategoryCode string `json:"treatment_category_code"`
+ Active bool `json:"active"`
+ Enabled bool `json:"enabled"`
+ CreateDate time.Time `json:"create_at"`
+ UpdateDate time.Time `json:"update_at"`
+ CreatedUser User `json:"created_user"`
+}
+
+type ProviderAddress struct {
+ StreetAddress1 string `json:"street_address_1"`
+ StreetAddress2 string `json:"street_address_2"`
+ CityName string `json:"city"`
+ State string `json:"state"`
+ ZipCode string `json:"zipcode"`
+ Country string `json:"country"`
+ Latitude float64 `json:"lat"`
+ Longitude float64 `json:"long"`
+ PhoneNumber string `json:"phone_number"`
+}
+
+type ProviderResponse struct {
+ MukID string `json:"mukId"`
+ FivePartKeyGroups []PartKeyGroup `json:"fivePartKeyGroups"`
+ OrgName string `json:"orgName"`
+ Gender string `json:"gender"`
+ AcceptNewPatients string `json:"acceptNewPatients"`
+ ProviderName string `json:"providerName"`
+ FirstName string `json:"firstName"`
+ LastName string `json:"lastName"`
+ MiddleName string `json:"middleName"`
+ ProviderTitle string `json:"providerTitle"`
+ StreetName1 string `json:"streetName_1"`
+ StreetName2 string `json:"streetName_2"`
+ CityName string `json:"cityName"`
+ State string `json:"state"`
+ ZipCode string `json:"zipCode"`
+ Country string `json:"country"`
+ Latitude string `json:"latitude"`
+ Longitude string `json:"longitude"`
+ PhoneNumber string `json:"phoneNumber"`
+ ProviderEntityName string `json:"providerEntityName"`
+ ProviderEntityCode string `json:"providerEntityCode"`
+ ProviderTypeCode []ProviderTypeCode `json:"providerTypeCode"`
+ Distance string `json:"distance"`
+ AvailabilityOfCost string `json:"availabilityOfCost"`
+ TDDPhoneNumber string `json:"tddPhoneNumber"`
+ ExtendedOfficeHours string `json:"extendedOfficeHours"`
+ ProviderCountyCode string `json:"providerCountyCode"`
+ ProviderCountyName string `json:"providerCountyName"`
+ HospitalAffiliationNames []HospitalAffiliationNames `json:"hospitalAffiliationNames"`
+ ProviderAffiliationNumber string `json:"providerAffiliationNumber"`
+ ProviderAffiliationName string `json:"providerAffiliationName"`
+ LanguagesSpoken []Languages `json:"languagesSpoken"`
+ OfficeLanguagesSpoken []Languages `json:"officeLanguagesSpoken"`
+ MedSchool string `json:"medSchool"`
+ MedSchoolYear string `json:"medSchoolYear"`
+ Internship string `json:"internship"`
+ Residence string `json:"residency"`
+ Specialty1 string `json:"specialty1"`
+ Specialty2 string `json:"specialty2"`
+ Specialty3 string `json:"specialty3"`
+ Specialty4 string `json:"specialty4"`
+ Certification1 string `json:"certification1"`
+ Certification2 string `json:"certification2"`
+ Certification3 string `json:"certification3"`
+ Certification4 string `json:"certification4"`
+}
+
+type HospitalAffiliationNames struct {
+ HospAffProvOrgName string `json:"hospAffProvOrgName"`
+}
+
+type Languages struct {
+ Code string `json:"code"`
+}
+
+type ProviderTypeCode struct {
+ Code string `json:"code"`
+}
+
+type PartKeyGroup struct {
+ ProviderNum string `json:"providerNum"`
+ ProviderNumSuffix string `json:"providerNumSuffix"`
+ LocationSeqNum string `json:"locationSeqNum"`
+ PlanCode string `json:"planCode"`
+ ProductID string `json:"productId"`
+ TreatmentCategoryCode string `json:"treatmentCategoryCode"`
+}
diff --git a/domain/entity/ride.go b/domain/entity/ride.go
new file mode 100644
index 0000000..f720577
--- /dev/null
+++ b/domain/entity/ride.go
@@ -0,0 +1,116 @@
+package entity
+
+import (
+ "time"
+)
+
+//WebhookResponse has the data and events from the webhook
+type WebhookResponse struct {
+ EventID string `json:"event_id,omitempty"`
+ HREF string `json:"href,omitempty"`
+ OccurredAt time.Time `json:"occurred_at,omitempty"`
+ EventType string `json:"event_type,omitempty"`
+ Ride Ride `json:"event,omitempty"`
+}
+
+// Ride entity data
+type Ride struct {
+ ID int64 `db:"ride_id" json:"-"`
+ UUID string `db:"ride_uuid" json:"ride_uuid"`
+ User User `db:"user" json:"user"`
+ Status RideStatus `db:"status" json:"status"`
+ Type RideType `db:"type" json:"type"`
+ InternalID string `db:"internal_id" json:"internal_id"`
+ RequestDate *time.Time `db:"request_date" json:"request_date"`
+ RequestMiliseconds *int64 `db:"request_ms" json:"request_ms"`
+ GenerateDate *time.Time `db:"generate_date" json:"generate_date"`
+ GenerateMiliseconds *int64 `db:"generate_ms" json:"generate_ms"`
+ Note string `db:"notes" json:"notes"`
+ PrimetimePercentage string `db:"primetime_percentage" json:"primetime_percentage"`
+ Passenger RidePassenger `db:"passenger" json:"passenger"`
+ Driver RideDriver `db:"driver" json:"driver"`
+ Vehicle RideVehicle `db:"vehicle" json:"vehicle"`
+ Route RideRoute `db:"route" json:"route"`
+ VisitDate *time.Time `db:"visit_date" json:"visit_date"`
+ VisitTime *time.Time `db:"visit_time" json:"visit_time"`
+ PickupTime *time.Time `db:"pickup_time" json:"pickup_time"`
+ Created time.Time `db:"create_at" json:"create_at"`
+ Updated time.Time `db:"update_at" json:"update_at"`
+ Visit Visit `db:"visit" json:"visit"`
+ CreatedUser User `db:"created_user" json:"created_user"`
+ TripType TripType `db:"trip_type" json:"trip_type"`
+}
+
+// RidePassenger entity data
+type RidePassenger struct {
+ ID int64 `db:"ride_passenger_id" json:"-"`
+ FirstName string `db:"first_name" json:"first_name"`
+ LastName string `db:"last_name" json:"last_name"`
+ ImageURL *string `db:"image_url" json:"image_url"`
+ PhoneNumber string `db:"phone_number" json:"phone_number"`
+ InternalID *string `db:"internal_id" json:"internal_id"`
+}
+
+// RideStatus entity data
+type RideStatus struct {
+ ID int64 `db:"ride_status_id" json:"-"`
+ Key string `db:"key" json:"key"`
+ Value string `db:"value" json:"value"`
+}
+
+// RideStatus entity data
+type TripType struct {
+ ID int64 `db:"trip_type_id" json:"-"`
+ Key string `db:"trip_type_key" json:"key"`
+ Value string `db:"trip_type" json:"value"`
+}
+
+// RideType entity data
+type RideType struct {
+ ID int64 `db:"ride_type_id" json:"-"`
+ Key string `db:"key" json:"key"`
+ Value string `db:"value" json:"value"`
+}
+
+// RideRoute entity data
+type RideRoute struct {
+ ID int64 `db:"ride_route_id" json:"-"`
+ Origin Location `db:"origin" json:"origin"`
+ Destination Location `db:"destination" json:"destination"`
+ RouteKML *string `db:"route_kml" json:"route_kml"`
+ Distance float64 `db:"distance" json:"distance"`
+ Duration int64 `db:"duration" json:"duration"`
+ ETA int64 `db:"eta" json:"eta"`
+ Created time.Time `db:"create_at" json:"create_at"`
+ Updated time.Time `db:"update_at" json:"update_at"`
+}
+
+// Location entity data
+type Location struct {
+ ID string `db:"id" json:"id"`
+ Name string `db:"name" json:"name"`
+ Address string `db:"address" json:"address"`
+ Latitude float64 `db:"lat" json:"lat"`
+ Longitude float64 `db:"lng" json:"lng"`
+}
+
+// RideDriver entity data
+type RideDriver struct {
+ ID int64 `db:"ride_driver_id" json:"-"`
+ Name string `db:"name" json:"name"`
+ ImageURL *string `db:"image_url" json:"image_url"`
+ PhoneNumber string `db:"phone_number" json:"phone_number"`
+ Rating *string `db:"rating" json:"rating"`
+}
+
+// RideVehicle entity data
+type RideVehicle struct {
+ ID int64 `db:"ride_vehicle_id" json:"-"`
+ Color string `db:"color" json:"color"`
+ ImageURL string `db:"image_url" json:"image_url"`
+ LicensePlate string `db:"license_plate" json:"license_plate"`
+ LicensePlateState string `db:"license_plate_state" json:"license_plate_state"`
+ Make string `db:"make" json:"make"`
+ Model string `db:"model" json:"model"`
+ Year int64 `db:"year" json:"year"`
+}
diff --git a/domain/entity/user.go b/domain/entity/user.go
new file mode 100644
index 0000000..1a95f1e
--- /dev/null
+++ b/domain/entity/user.go
@@ -0,0 +1,55 @@
+package entity
+
+import (
+ "strings"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+// User entity data
+type User struct {
+ ID int64 `db:"user_id" json:"-"`
+ UUID string `db:"user_uuid" json:"uuid"`
+ Name string `db:"name" json:"name"`
+ Member string `db:"member" json:"member"`
+ BirthDate time.Time `db:"birth_date" json:"birthdate"`
+ LoginID int64 `db:"login_id" json:"-"`
+ LoginUUID string `db:"login_uuid" json:"loginuuid"`
+ Email string `db:"email" json:"email"`
+ PhoneNumber string `db:"phone_number" json:"phonenumber"`
+ Pass string `db:"password" json:"pass"`
+ LoginKey string `db:"login_key" json:"loginkey"`
+ Gender string `db:"gender" json:"gender"`
+ Active bool `db:"active" json:"active"`
+ Created time.Time `db:"createat" json:"createat"`
+ Updated time.Time `db:"updateat" json:"updateat"`
+ Contacts []ContactInfo `db:"contacts" json:"contacts"`
+ Rides []Ride `db:"rides" json:"rides"`
+ Addresses []Address `db:"addresses" json:"addresses"`
+ Profiles []Profile `json:"profiles,omitempty"`
+ Types []OrganizationType `json:"types,omitempty"`
+ Organizations []Organization `json:"organizations,omitempty"`
+}
+
+type ContactInfo struct {
+ ID int64 `db:"contact_id" json:"contact_id"`
+ Type ContactType `db:"contact_type" json:"contact_type"`
+ UserID int64 `db:"user_id" json:"-"`
+ Value string `db:"value" json:"value"`
+}
+
+type ContactType struct {
+ ID int64 `db:"contact_type_id" json:"contact_type_id"`
+ Key string `db:"contact_type_key" json:"contact_type_key"`
+ Value string `db:"contact_type_value" json:"contact_type_value"`
+}
+
+// Validate validates the user entity state
+func (entity *User) Validate() error {
+ if strings.TrimSpace(entity.Name) == "" {
+ return errors.NewValidationError("name", "Nome do usuário é obrigatório")
+ }
+
+ return nil
+}
diff --git a/domain/entity/visit.go b/domain/entity/visit.go
new file mode 100644
index 0000000..9f04a9d
--- /dev/null
+++ b/domain/entity/visit.go
@@ -0,0 +1,35 @@
+package entity
+
+import (
+ "time"
+)
+
+// VisitStatus entity data
+type VisitStatus struct {
+ ID int64 `db:"visit_status_id" json:"-"`
+ Key string `db:"key" json:"key"`
+ Value string `db:"value" json:"value"`
+}
+
+// Visit entity data
+type Visit struct {
+ ID int64 `db:"visit_id" json:"-"`
+ UUID string `db:"visit_uuid" json:"-"`
+ Status VisitStatus `db:"visit_status" json:"-"`
+ User User `db:"user" json:"-"`
+ VisitDuration int64 `db:"visit_duration" json:"-"`
+ VisitDatetime time.Time `db:"visit_datetime" json:"-"`
+ PickupDatetime time.Time `db:"pickup_datetime" json:"-"`
+ Notes *string `db:"notes" json:"-"`
+ PickupAddressID int64 `db:"pickup_address_id" json:"-"`
+ DestinationAddressID int64 `db:"destination_address_id" json:"-"`
+ Pickup Location `db:"pickup" json:"-"`
+ Provider Provider `db:"provider" json:"-"`
+ CreatedUser User `db:"created_user" json:"-"`
+ Created time.Time `db:"created_date" json:"-"`
+ Updated time.Time `db:"updated_date" json:"-"`
+ ReturnDate *time.Time `db:"return_date" json:"-"`
+ TripType TripType `db:"trip_type" json:"-"`
+ ExternalID string `db:"visit_external_id" json:"-"`
+ Rides []Ride `db:"rides" json:"-"`
+}
diff --git a/domain/service/notification.go b/domain/service/notification.go
new file mode 100644
index 0000000..04ed2b8
--- /dev/null
+++ b/domain/service/notification.go
@@ -0,0 +1,36 @@
+package service
+
+import "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+
+// userService is the domain service for user operations
+type notificationService struct {
+ svc *Service
+}
+
+// newUserService returns an instance of userService
+func newNotificationService(svc *Service) *notificationService {
+ return ¬ificationService{
+ svc: svc,
+ }
+}
+
+// Save the ride for a expected user
+func (s *notificationService) Create(notification entity.Notification) (entity.Notification, error) {
+ return s.svc.db.Notification().Create(notification)
+}
+
+func (c *notificationService) GetByUserUUIDAndReadStatus(userUUID string, status string, isRead bool) ([]entity.Notification, error) {
+ return c.svc.db.Notification().GetByUserUUIDAndReadStatus(userUUID, status, isRead)
+}
+
+func (c *notificationService) GetByUserUUID(userUUID string, status string) ([]entity.Notification, error) {
+ return c.svc.db.Notification().GetByUserUUID(userUUID, status)
+}
+
+func (c *notificationService) ReadStatus(notificationUUID string, isRead bool) error {
+ return c.svc.db.Notification().ReadStatus(notificationUUID, isRead)
+}
+
+func (c *notificationService) GetLastNotificationFromPhoneNumber(notificationType string, phoneNumber string, status string) (entity.Notification, error) {
+ return c.svc.db.Notification().GetLastNotificationFromPhoneNumber(notificationType, phoneNumber, status)
+}
diff --git a/domain/service/organization.go b/domain/service/organization.go
new file mode 100644
index 0000000..79e72d2
--- /dev/null
+++ b/domain/service/organization.go
@@ -0,0 +1,113 @@
+package service
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// userService is the domain service for user operations
+type organizationService struct {
+ svc *Service
+}
+
+// newUserService returns an instance of userService
+func newOrganizationService(svc *Service) *organizationService {
+ return &organizationService{
+ svc: svc,
+ }
+}
+
+func (s *organizationService) GetAllTypes() ([]entity.OrganizationType, error) {
+ return s.svc.db.Organization().GetAllTypes()
+}
+
+func (s *organizationService) GetByType(organizationTypeKey string) ([]entity.Organization, error) {
+ return s.svc.db.Organization().GetByType(organizationTypeKey)
+}
+
+func (s *organizationService) GetByName(name string, searchType string) ([]entity.Organization, error) {
+ return s.svc.db.Organization().GetByName(name, searchType)
+}
+
+func (s *organizationService) GetByUUID(organizationUUID string) (entity.Organization, error) {
+ organization, err := s.svc.db.Organization().GetByUUID(organizationUUID)
+ if err != nil {
+ return organization, err
+ }
+
+ organization.Contacts, err = s.GetContactsByOrganizationID(organization.ID)
+ if err != nil {
+ return organization, err
+ }
+
+ organization.Addresses, err = s.GetAddressByOrganizationID(organization.ID)
+ if err != nil {
+ return organization, err
+ }
+
+ organization.ChildOrgs, err = s.svc.db.Organization().GetChildsByID(organization.ID)
+ if err != nil {
+ return organization, err
+ }
+
+ if organization.ParentID > 0 {
+ parent, err := s.svc.db.Organization().GetByID(organization.ParentID)
+ if err != nil {
+ return organization, err
+ }
+ organization.Parent = &parent
+ }
+
+ return organization, nil
+}
+
+func (s *organizationService) SetParentOrganization(organizationID int64, parentOrganizationID int64) error {
+ return s.svc.db.Organization().SetParentOrganization(organizationID, parentOrganizationID)
+}
+
+func (s *organizationService) GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error) {
+ return s.svc.db.Organization().GetContactsByOrganizationUUID(organizationUUID)
+}
+
+func (s *organizationService) GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error) {
+ return s.svc.db.Organization().GetContactsByOrganizationID(organizationID)
+}
+
+func (s *organizationService) GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error) {
+ return s.svc.db.Organization().GetContactsByUUID(contactUUID)
+}
+
+func (s *organizationService) GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error) {
+ return s.svc.db.Organization().GetAddressByOrganizationUUID(organizationUUID)
+}
+
+func (s *organizationService) GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error) {
+ return s.svc.db.Organization().GetAddressByOrganizationID(organizationID)
+}
+
+func (s *organizationService) GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error) {
+ return s.svc.db.Organization().GetAddressByUUID(contactUUID)
+}
+
+func (s *organizationService) InactivateOrganizationAddress(address entity.OrganizationAddress) error {
+ return s.svc.db.Organization().InactivateOrganizationAddress(address)
+}
+
+func (s *organizationService) SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) {
+ return s.svc.db.Organization().SetOrganizationAddress(address)
+}
+
+func (s *organizationService) InactivateOrganizationContact(contact entity.OrganizationContact) error {
+ return s.svc.db.Organization().InactivateOrganizationContact(contact)
+}
+
+func (s *organizationService) SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) {
+ return s.svc.db.Organization().SetOrganizationContact(contact)
+}
+
+func (s *organizationService) AddOrganization(organization entity.Organization) (entity.Organization, error) {
+ return s.svc.db.Organization().AddOrganization(organization)
+}
+
+func (s *organizationService) GetTypeByKey(key string) (entity.OrganizationType, error) {
+ return s.svc.db.Organization().GetTypeByKey(key)
+}
diff --git a/domain/service/profile.go b/domain/service/profile.go
new file mode 100644
index 0000000..278d874
--- /dev/null
+++ b/domain/service/profile.go
@@ -0,0 +1,33 @@
+package service
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// userService is the domain service for user operations
+type profileService struct {
+ svc *Service
+}
+
+// newUserService returns an instance of userService
+func newProfileService(svc *Service) *profileService {
+ return &profileService{
+ svc: svc,
+ }
+}
+
+func (s *profileService) GetAll() ([]entity.Profile, error) {
+ return s.svc.db.Profile().GetAll()
+}
+
+func (s *profileService) GetByKey(key string) (entity.Profile, error) {
+ return s.svc.db.Profile().GetByKey(key)
+}
+
+func (s *profileService) GetVisibles(visible bool) ([]entity.Profile, error) {
+ return s.svc.db.Profile().GetVisibles(visible)
+}
+
+func (s *profileService) GetByOrganizationType(organizationTypeID int64) ([]entity.Profile, error) {
+ return s.svc.db.Profile().GetByOrganizationType(organizationTypeID)
+}
diff --git a/domain/service/provider.go b/domain/service/provider.go
new file mode 100644
index 0000000..ee03dfe
--- /dev/null
+++ b/domain/service/provider.go
@@ -0,0 +1,46 @@
+package service
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// userService is the domain service for user operations
+type providerService struct {
+ svc *Service
+}
+
+// newUserService returns an instance of userService
+func newProviderService(svc *Service) *providerService {
+ return &providerService{
+ svc: svc,
+ }
+}
+
+// Save the ride for a expected user
+func (s *providerService) Save(providers []entity.ProviderResponse, user entity.User) ([]entity.Provider, error) {
+ tx, err := s.svc.db.Begin()
+ if err != nil {
+ return nil, err
+ }
+
+ newProviders, err := tx.Provider().Save(providers, user)
+ if err != nil {
+ tx.Rollback()
+ return nil, err
+ }
+ tx.Commit()
+
+ return newProviders, nil
+}
+
+func (s *providerService) GetAll(user entity.User) ([]entity.Provider, error) {
+ return s.svc.db.Provider().GetAll(user)
+}
+
+func (s *providerService) Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user entity.User) ([]entity.Provider, error) {
+ return s.svc.db.Provider().Get(query, lat, long, distance, planCode, productID, mukID, internalID, sort, user)
+}
+
+func (s *providerService) GetByMukID(mukID string, user entity.User) (entity.Provider, error) {
+ return s.svc.db.Provider().GetByMukID(mukID, user)
+}
diff --git a/domain/service/ride.go b/domain/service/ride.go
new file mode 100644
index 0000000..6437d10
--- /dev/null
+++ b/domain/service/ride.go
@@ -0,0 +1,103 @@
+package service
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// userService is the domain service for user operations
+type rideService struct {
+ svc *Service
+}
+
+// newUserService returns an instance of userService
+func newRideService(svc *Service) *rideService {
+ return &rideService{
+ svc: svc,
+ }
+}
+
+// Save the ride for a expected user
+func (s *rideService) Save(ride entity.Ride) (entity.Ride, error) {
+ ride, err := s.svc.db.Rides().Save(ride)
+ if err != nil {
+ return ride, err
+ }
+
+ user, err := s.svc.db.Users().GetByID(ride.CreatedUser.ID)
+ if err != nil {
+ return ride, err
+ }
+
+ return s.GetByUUID(ride.UUID, user)
+}
+
+func (s *rideService) Update(hook entity.WebhookResponse) (entity.Ride, error) {
+ user, err := s.svc.db.Users().GetByID(hook.Ride.CreatedUser.ID)
+ if err != nil {
+ return entity.Ride{}, err
+ }
+
+ ride, err := s.svc.db.Rides().Update(hook, user)
+ if err != nil {
+ return ride, err
+ }
+
+ return s.GetByUUID(ride.UUID, user)
+}
+
+// GetAll return all rides
+func (s *rideService) GetAll(user entity.User) ([]entity.Ride, error) {
+ return s.svc.db.Rides().GetAll(user)
+}
+
+func (s *rideService) GetByID(id int64, user entity.User) (entity.Ride, error) {
+ return s.svc.db.Rides().GetByID(id, user)
+}
+
+// GetByUUID return a specific ride
+func (s *rideService) GetByUUID(uuid string, user entity.User) (entity.Ride, error) {
+ return s.svc.db.Rides().GetByUUID(uuid, user)
+}
+
+// GetByUUID return a specific ride
+func (s *rideService) GetByUUIDAndUserUUID(UUID string, userUUID string) (entity.Ride, error) {
+ return s.svc.db.Rides().GetByUUIDAndUserUUID(UUID, userUUID)
+}
+
+// GetByUUID return a specific ride
+func (s *rideService) GetByInternalID(internalID string) (entity.Ride, error) {
+ return s.svc.db.Rides().GetByInternalID(internalID)
+}
+
+// GetByUserID return a list of rides
+func (s *rideService) GetByUserID(userID int64, user entity.User) ([]entity.Ride, error) {
+ return s.svc.db.Rides().GetByUserID(userID, user)
+}
+
+func (s *rideService) GetByUserUUID(userUUID string, user entity.User) ([]entity.Ride, error) {
+ return s.svc.db.Rides().GetByUserUUID(userUUID, user)
+}
+
+func (s *rideService) UpdateStatus(rideUUID string, status string) error {
+ return s.svc.db.Rides().UpdateStatus(rideUUID, status)
+}
+
+func (s *rideService) GetLastRideByPhoneNumber(phoneNumber string) (entity.Ride, error) {
+ return s.svc.db.Rides().GetLastRideByPhoneNumber(phoneNumber)
+}
+
+func (s *rideService) GetLastRideByDriversNumber(phoneNumber string) (entity.Ride, error) {
+ return s.svc.db.Rides().GetLastRideByDriversNumber(phoneNumber)
+}
+
+func (s *rideService) GetByInternalPassengerID(internalPassengerID string) (entity.Ride, error) {
+ return s.svc.db.Rides().GetByInternalPassengerID(internalPassengerID)
+}
+
+func (s *rideService) GetByVisitUUID(visitUUID string, user entity.User) ([]entity.Ride, error) {
+ return s.svc.db.Rides().GetByVisitUUID(visitUUID, user)
+}
+
+func (s *rideService) GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user entity.User) (entity.Ride, error) {
+ return s.svc.db.Rides().GetByVisitUUIDAndTripType(visitUUID, tripTypeKey, user)
+}
diff --git a/domain/service/service.go b/domain/service/service.go
new file mode 100644
index 0000000..6030b05
--- /dev/null
+++ b/domain/service/service.go
@@ -0,0 +1,45 @@
+package service
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/logger"
+)
+
+var (
+ instance *Service
+ once sync.Once
+)
+
+// Service holds the domain service repositories
+type Service struct {
+ db contract.DataManager
+ cache contract.CacheManager
+ tnc contract.TNCManager
+ Users *userService
+ Rides *rideService
+ Visits *visitService
+ Provider *providerService
+ Notification *notificationService
+ Profile *profileService
+ Organization *organizationService
+}
+
+// New returns a new domain Service instance
+func New(db contract.DataManager, cache contract.CacheManager, cfg *config.Config, log *logger.Logger) (*Service, error) {
+ once.Do(func() {
+ instance = &Service{db: db, cache: cache}
+
+ instance.Users = newUserService(instance)
+ instance.Rides = newRideService(instance)
+ instance.Visits = newVisitService(instance)
+ instance.Provider = newProviderService(instance)
+ instance.Notification = newNotificationService(instance)
+ instance.Profile = newProfileService(instance)
+ instance.Organization = newOrganizationService(instance)
+ })
+
+ return instance, nil
+}
diff --git a/domain/service/tnc.go b/domain/service/tnc.go
new file mode 100644
index 0000000..1a50e13
--- /dev/null
+++ b/domain/service/tnc.go
@@ -0,0 +1,28 @@
+package service
+
+// tncService is the domain service for transportation network operations
+type tncService struct {
+ svc *Service
+}
+
+// newTncService returns an instance of tncService
+func newTncService(svc *Service) *tncService {
+ return &tncService{
+ svc: svc,
+ }
+}
+
+//GetETA will return the list of ETA's for the current location
+func (s *tncService) GetETA(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
+ return s.svc.tnc.GetETA(lag, log, params)
+}
+
+//GetDrivers return the drivers for the current location
+func (s *tncService) GetDrivers(lag float64, log float64) (interface{}, error) {
+ return s.svc.tnc.GetDrivers(lag, log)
+}
+
+//GetTypes will return the available types of ride for the current location
+func (s *tncService) GetTypes(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
+ return s.svc.tnc.GetTypes(lag, log, params)
+}
diff --git a/domain/service/user.go b/domain/service/user.go
new file mode 100644
index 0000000..844c979
--- /dev/null
+++ b/domain/service/user.go
@@ -0,0 +1,92 @@
+package service
+
+import (
+ "fmt"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+)
+
+// userService is the domain service for user operations
+type userService struct {
+ svc *Service
+}
+
+// newUserService returns an instance of userService
+func newUserService(svc *Service) *userService {
+ return &userService{
+ svc: svc,
+ }
+}
+
+// GetAll returns a list of users
+func (s *userService) GetAll() (list []entity.User, err error) {
+ return s.svc.db.Users().GetAll()
+}
+
+// GetByID returns a specific user by its ID
+func (s *userService) GetByID(userID int64) (entity.User, error) {
+ return s.svc.db.Users().GetByID(userID)
+}
+
+// GetByID returns a specific user by its ID
+func (s *userService) GetByUUID(uuid string, profile string) (entity.User, error) {
+ return s.svc.db.Users().GetByUUID(uuid, profile)
+}
+
+// Login returns a specific user by email and pass
+func (s *userService) Login(email string, pass string) (entity.User, error) {
+ return s.svc.db.Users().Login(email, pass)
+}
+
+// Login returns a specific user by email and pass
+func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (entity.User, error) {
+ return s.svc.db.Users().FullLogin(loginType, key, pass, profile)
+}
+
+// Login returns a specific user by email and pass
+func (s *userService) Create(user entity.User) (entity.User, error) {
+ return s.svc.db.Users().Create(user)
+}
+
+func (s *userService) CreateBulk(users []entity.User) ([]entity.User, error) {
+ tx, err := s.svc.db.Begin()
+ if err != nil {
+ return nil, err
+ }
+
+ for i, _ := range users {
+ users[i], err = tx.Users().Create(users[i])
+ if err != nil {
+ fmt.Println(fmt.Sprintf("Email %s got error: %s", users[i].Email, err.Error()))
+ tx.Rollback()
+ return nil, err
+ }
+ fmt.Println(fmt.Sprintf("Email %s created", users[i].Email))
+ }
+
+ tx.Commit()
+ return users, nil
+}
+
+// GetUsersByProfile returns a list of users by profile
+func (s *userService) GetUsersByProfile(profile string) ([]entity.User, error) {
+ return s.svc.db.Users().GetUsersByProfile(profile)
+}
+
+func (s *userService) RemoveAddress(addressUUID string) error {
+ return s.svc.db.Users().RemoveAddress(addressUUID)
+}
+
+// SaveAddress returns a list of users by profile
+func (s *userService) SaveAddress(address entity.Address) (entity.Address, error) {
+ return s.svc.db.Users().SaveAddress(address)
+}
+
+// GetAddressByUUID returns a list of users by profile
+func (s *userService) GetAddressByUUID(addressUUID string) (entity.Address, error) {
+ return s.svc.db.Users().GetAddressByUUID(addressUUID)
+}
+
+func (s *userService) GetContactType() (retVal []entity.ContactType, err error) {
+ return s.svc.db.Users().GetContactType()
+}
diff --git a/domain/service/visit.go b/domain/service/visit.go
new file mode 100644
index 0000000..dd89224
--- /dev/null
+++ b/domain/service/visit.go
@@ -0,0 +1,81 @@
+package service
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/domain/entity"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+// userService is the domain service for user operations
+type visitService struct {
+ svc *Service
+}
+
+// newUserService returns an instance of userService
+func newVisitService(svc *Service) *visitService {
+ return &visitService{
+ svc: svc,
+ }
+}
+
+// Save the ride for a expected user
+func (s *visitService) Create(visit entity.Visit) (entity.Visit, error) {
+ return s.svc.db.Visits().Create(visit)
+}
+
+// Save the ride for a expected user
+func (s *visitService) GetAll(user entity.User) ([]entity.Visit, error) {
+ visit, err := s.svc.db.Visits().GetAll(user)
+ if err != nil {
+ return nil, err
+ }
+
+ rides, err := s.svc.db.Rides().GetAll(user)
+ if err != nil {
+ return nil, err
+ }
+
+ ridesByVisit := make(map[int64][]entity.Ride)
+ for _, r := range rides {
+ rides := ridesByVisit[r.Visit.ID]
+ rides = append(rides, r)
+ ridesByVisit[r.Visit.ID] = rides
+ }
+
+ for i, v := range visit {
+ visit[i].Rides = ridesByVisit[v.ID]
+ }
+
+ return visit, nil
+}
+
+// Save the ride for a expected user
+func (s *visitService) GetByUUID(visitUUID string, user entity.User) (entity.Visit, error) {
+ visit, err := s.svc.db.Visits().GetByUUID(visitUUID, user)
+ if err != nil {
+ return entity.Visit{}, errors.Wrap(err)
+ }
+
+ rides, err := s.svc.db.Rides().GetByVisitUUID(visitUUID, user)
+ if err != nil {
+ return entity.Visit{}, errors.Wrap(err)
+ }
+ visit.Rides = rides
+
+ return visit, nil
+}
+
+// Save the ride for a expected user
+func (s *visitService) GetByID(visitID int64, user entity.User) (entity.Visit, error) {
+ visit, err := s.svc.db.Visits().GetByID(visitID, user)
+ if err != nil {
+ return entity.Visit{}, errors.Wrap(err)
+ }
+
+ rides, err := s.svc.db.Rides().GetByVisitUUID(visit.UUID, user)
+ if err != nil {
+ return entity.Visit{}, errors.Wrap(err)
+ }
+ visit.Rides = rides
+
+ return visit, nil
+}
diff --git a/ecs.dev.json b/ecs.dev.json
new file mode 100644
index 0000000..511b6d5
--- /dev/null
+++ b/ecs.dev.json
@@ -0,0 +1,35 @@
+{
+ "containerDefinitions": [
+ {
+ "name": "api-development",
+ "image": "xxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/dev.nemt-portal-api:latest",
+ "cpu": 128,
+ "memory": 128,
+ "essential": true,
+ "logConfiguration": {
+ "logDriver": "awslogs",
+ "options": {
+ "awslogs-group": "nemt-portal-api",
+ "awslogs-region": "sa-east-1",
+ "awslogs-stream-prefix": "development"
+ }
+ },
+ "portMappings": [
+ {
+ "containerPort": 5100
+ }
+ ],
+ "environment": [
+ {
+ "name": "SERVICE_5100_NAME",
+ "value": "portal-api"
+ },
+ {
+ "name": "SERVICE_5100_TAG",
+ "value": "api"
+ }
+ ]
+ }
+ ],
+ "family": "api-development"
+}
\ No newline at end of file
diff --git a/ecs.prd.json b/ecs.prd.json
new file mode 100644
index 0000000..076f043
--- /dev/null
+++ b/ecs.prd.json
@@ -0,0 +1,35 @@
+{
+ "containerDefinitions": [
+ {
+ "name": "portal-api-prod",
+ "image": "105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:prod",
+ "cpu": 128,
+ "memory": 128,
+ "essential": true,
+ "logConfiguration": {
+ "logDriver": "awslogs",
+ "options": {
+ "awslogs-group": "portal-api",
+ "awslogs-region": "us-east-2",
+ "awslogs-stream-prefix": "prod"
+ }
+ },
+ "portMappings": [
+ {
+ "containerPort": 5100
+ }
+ ],
+ "environment": [
+ {
+ "name": "SERVICE_5100_NAME",
+ "value": "portal-api"
+ },
+ {
+ "name": "SERVICE_5100_TAGS",
+ "value": "api"
+ }
+ ]
+ }
+ ],
+ "family": "portal-api-prod"
+}
\ No newline at end of file
diff --git a/ecs.stg.json b/ecs.stg.json
new file mode 100644
index 0000000..1ea720d
--- /dev/null
+++ b/ecs.stg.json
@@ -0,0 +1,35 @@
+{
+ "containerDefinitions": [
+ {
+ "name": "portal-api-dev",
+ "image": "105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:dev",
+ "cpu": 128,
+ "memory": 128,
+ "essential": true,
+ "logConfiguration": {
+ "logDriver": "awslogs",
+ "options": {
+ "awslogs-group": "portal-api",
+ "awslogs-region": "us-east-2",
+ "awslogs-stream-prefix": "test"
+ }
+ },
+ "portMappings": [
+ {
+ "containerPort": 5100
+ }
+ ],
+ "environment": [
+ {
+ "name": "SERVICE_5100_NAME",
+ "value": "portal-api"
+ },
+ {
+ "name": "SERVICE_5100_TAGS",
+ "value": "api"
+ }
+ ]
+ }
+ ],
+ "family": "portal-api-dev"
+}
\ No newline at end of file
diff --git a/glide.yaml b/glide.yaml
new file mode 100644
index 0000000..09aa359
--- /dev/null
+++ b/glide.yaml
@@ -0,0 +1,44 @@
+package: bitbucket.org/nemt/nemt-portal-api
+import:
+- package: github.com/Sirupsen/logrus
+ version: ~1.0.2
+- package: github.com/dgrijalva/jwt-go
+ version: ~3.0.0
+- package: github.com/go-sql-driver/mysql
+ version: ~1.3.0
+- package: github.com/labstack/echo
+ version: ~3.2.1
+ subpackages:
+ - middleware
+- package: github.com/labstack/gommon
+ version: ~0.2.2
+ subpackages:
+ - log
+- package: github.com/spf13/viper
+- package: gopkg.in/redis.v5
+ version: ~5.2.9
+- package: github.com/didip/tollbooth
+- package: github.com/lyft/lyft-go-sdk
+ subpackages:
+ - lyft
+- package: github.com/pquerna/ffjson
+- package: github.com/graarh/golang-socketio
+- package: github.com/gorilla/websocket
+- package: github.com/justwatchcom/goat
+- package: googlemaps.github.io/maps
+- package: gopkg.in/gomail.v2
+ version: ~2.0.0
+- package: github.com/srajelli/ses-go
+- package: github.com/aws/aws-sdk-go
+ version: ~1.12.66
+- package: google.golang.org/api
+ subpackages:
+ - urlshortener/v1
+- package: golang.org/x/oauth2
+ subpackages:
+ - google
+- package: github.com/ttacon/libphonenumber
+ version: ~1.0.0
+- package: github.com/ttacon/builder
+- package: github.com/casbin/casbin
+ version: ~1.5.0
diff --git a/infra/auth/auth.go b/infra/auth/auth.go
new file mode 100644
index 0000000..6338339
--- /dev/null
+++ b/infra/auth/auth.go
@@ -0,0 +1,153 @@
+package auth
+
+import (
+ "crypto/rsa"
+ "fmt"
+ "io/ioutil"
+ "time"
+
+ "github.com/pquerna/ffjson/ffjson"
+
+ "strings"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ jwt "github.com/dgrijalva/jwt-go"
+ "github.com/labstack/echo"
+)
+
+const (
+ // AppKeyHeaderName is the header name for application keys
+ AppKeyHeaderName = "App"
+ // AppTokenHeaderName is the header name for application token
+ AppTokenHeaderName = "Token"
+ // TokenExpiration is the auth token default expiration time
+ TokenExpiration = 24 * time.Hour
+)
+
+var (
+ // TokenSigningMethod is the auth token signing algorithm
+ TokenSigningMethod = jwt.SigningMethodRS256
+)
+
+// GetAppKeyFromContext returns the application key from request header
+func GetAppKeyFromContext(ctx echo.Context) (appKey string, err error) {
+ appKey = ctx.Request().Header.Get(AppKeyHeaderName)
+
+ if strings.TrimSpace(appKey) == "" {
+ return "", errors.NewNotAuthorizedError("Application key not found")
+ }
+
+ return appKey, nil
+}
+
+// ValidateAppKey validates the presence and validity of App key
+func ValidateAppKey(ctx echo.Context, cfg *config.Config) (err error) {
+ appKey, err := GetAppKeyFromContext(ctx)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ if appKey != cfg.HTTP.Auth.AppKey {
+ return errors.NewNotAuthorizedError("Invalid API Key")
+ }
+
+ return nil
+}
+
+// GetCertPrivateKey returns the private key for the token authentication certificate
+func GetCertPrivateKey(path string) (pk *rsa.PrivateKey, err error) {
+ data, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ pk, err = jwt.ParseRSAPrivateKeyFromPEM(data)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ return pk, nil
+}
+
+// GetCertPublicKey returns the public key for the token authentication certificate
+func GetCertPublicKey(path string) (pk *rsa.PublicKey, err error) {
+ privateKey, err := GetCertPrivateKey(path)
+ if err != nil {
+ return nil, errors.Wrap(err)
+ }
+
+ return &privateKey.PublicKey, nil
+}
+
+// GenerateToken creates a token based on certificate
+func GenerateToken(cfg *config.Config, data interface{}) (tokenString string, err error) {
+ key, _ := GetCertPrivateKey(cfg.HTTP.Auth.CertificatePath)
+
+ claims := jwt.MapClaims{
+ "iat": time.Now().Unix(),
+ "exp": time.Now().Add(TokenExpiration).Unix(),
+ "iss": "BDC",
+ "sub": "NEMT",
+ "data": data,
+ }
+
+ token := jwt.NewWithClaims(TokenSigningMethod, claims)
+ tokenString, err = token.SignedString(key)
+ if err != nil {
+ return tokenString, errors.Wrap(err)
+ }
+
+ return tokenString, nil
+}
+
+func GetTokenDetail(ctx echo.Context, cfg *config.Config) (interface{}, error) {
+ key, _ := GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
+
+ tokenString := ctx.Request().Header.Get("Token")
+ tokenString = strings.Replace(tokenString, "Bearer ", "", -1)
+
+ token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
+ if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
+ return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
+ }
+ return key, nil
+ })
+
+ if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
+ return claims["data"], nil
+ } else {
+ return nil, err
+ }
+}
+
+func GetUserDetail(ctx echo.Context, cfg *config.Config) (viewmodel.User, error) {
+ key, _ := GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
+
+ tokenString := ctx.Request().Header.Get("Token")
+ tokenString = strings.Replace(tokenString, "Bearer ", "", -1)
+
+ token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
+ if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
+ return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
+ }
+ return key, nil
+ })
+ if err != nil {
+ return viewmodel.User{}, err
+ }
+
+ if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
+ byteData, _ := ffjson.Marshal(claims["data"])
+ user := viewmodel.User{}
+ err = ffjson.Unmarshal(byteData, &user)
+ if err != nil {
+ return viewmodel.User{}, err
+ } else {
+ return user, nil
+ }
+ } else {
+ return viewmodel.User{}, err
+ }
+}
diff --git a/infra/aws/aws.go b/infra/aws/aws.go
new file mode 100644
index 0000000..0c39fce
--- /dev/null
+++ b/infra/aws/aws.go
@@ -0,0 +1,109 @@
+package aws
+
+import (
+ "bytes"
+
+ "net/http"
+ "path"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/aws/aws-sdk-go/aws"
+ "github.com/aws/aws-sdk-go/aws/session"
+ "github.com/aws/aws-sdk-go/service/s3"
+ "github.com/aws/aws-sdk-go/service/s3/s3manager"
+ "github.com/aws/aws-sdk-go/service/ssm"
+)
+
+//AWSUtil return the methods to interact with AWS Services
+type AWSUtil struct {
+ configApp *config.Config
+ awsConfig *aws.Config
+ s3Service *s3.S3
+ ssmService *ssm.SSM
+ awsSession *session.Session
+}
+
+//New return an instance of AWSUtil
+func New(configApp *config.Config) *AWSUtil {
+ cfg := aws.NewConfig().WithRegion("sa-east-1")
+ cfg.DisableRestProtocolURICleaning = aws.Bool(true)
+
+ return &AWSUtil{
+ configApp: configApp,
+ awsConfig: cfg,
+ s3Service: s3.New(session.New(), cfg),
+ ssmService: ssm.New(session.New(), cfg),
+ awsSession: session.New(cfg),
+ }
+}
+
+//DownloadFromS3Bucket will return the file on the S3 Bucket
+func (a AWSUtil) DownloadFromS3Bucket(filePath string) ([]byte, error) {
+ downloader := s3manager.NewDownloader(a.awsSession)
+
+ b := &aws.WriteAtBuffer{}
+ _, err := downloader.Download(b, &s3.GetObjectInput{
+ Bucket: aws.String(a.configApp.Aws.S3Bucket),
+ Key: aws.String(filePath),
+ })
+
+ if err != nil {
+ return []byte{}, err
+ } else {
+ return b.Bytes(), nil
+ }
+}
+
+//UploadToS3Bucket will upload a file to the S3 Bucket
+func (a AWSUtil) UploadToS3Bucket(filePath string, fileName string, buff []byte) error {
+ fileBytes := bytes.NewReader(buff)
+ fileType := http.DetectContentType(buff)
+
+ fullPath := path.Join(filePath, fileName)
+
+ params := &s3.PutObjectInput{
+ Bucket: aws.String(a.configApp.Aws.S3Bucket),
+ Key: aws.String(fullPath),
+ Body: fileBytes,
+ ContentLength: aws.Int64(int64(len(buff))),
+ ContentType: aws.String(fileType),
+ }
+
+ _, err := a.s3Service.PutObject(params)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+//SsmPutParameter put parameter to SSM
+func (a AWSUtil) SsmPutParameter(parameterName string, parameterValue string) error {
+ params := &ssm.PutParameterInput{
+ Name: aws.String(parameterName),
+ Type: aws.String("SecureString"),
+ Value: aws.String(parameterValue),
+ }
+
+ _, err := a.ssmService.PutParameter(params)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+//SsmGetParameter get parameter from SSM
+func (a AWSUtil) SsmGetParameter(parameterName string, withDecryption bool) (string, error) {
+ params := &ssm.GetParameterInput{
+ Name: aws.String(parameterName),
+ WithDecryption: aws.Bool(withDecryption),
+ }
+
+ output, err := a.ssmService.GetParameter(params)
+ if err != nil {
+ return "", err
+ }
+
+ return (*output.Parameter.Value), nil
+}
diff --git a/infra/cache/cache.go b/infra/cache/cache.go
new file mode 100644
index 0000000..d7c4f31
--- /dev/null
+++ b/infra/cache/cache.go
@@ -0,0 +1,144 @@
+package cache
+
+import (
+ "encoding/json"
+ "fmt"
+
+ redis "gopkg.in/redis.v5"
+
+ "time"
+
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain"
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+)
+
+var (
+ instance *RedisCache
+ once sync.Once
+)
+
+// RedisCache implements the CacheManager interface
+type RedisCache struct {
+ cfg *config.Config
+ redis *redis.Client
+}
+
+// Instance returns a CacheManager instance
+func Instance(cfg *config.Config) contract.CacheManager {
+ once.Do(func() {
+ client := redis.NewFailoverClient(&redis.FailoverOptions{
+ MasterName: "master01",
+ SentinelAddrs: []string{fmt.Sprintf("%s:%v", cfg.Cache.Server, cfg.Cache.Port)},
+ Password: cfg.Cache.Pass,
+ DB: cfg.Cache.DB,
+ })
+
+ instance = &RedisCache{cfg, client}
+ })
+
+ return instance
+}
+
+func (r *RedisCache) buildKey(key string) string {
+ return fmt.Sprintf("%s-%s", r.cfg.Cache.Prefix, key)
+}
+
+// GetItem returns an Item from cache
+func (r *RedisCache) GetItem(key string) (data []byte, err error) {
+ val, err := r.redis.Get(r.buildKey(key)).Bytes()
+ if err == redis.Nil {
+ return val, domain.ErrCacheMiss
+ } else if err != nil {
+ return val, errors.Wrap(err)
+ }
+
+ return val, nil
+}
+
+// SetItem sets an item in cache
+func (r *RedisCache) SetItem(key string, data []byte) error {
+ err := r.redis.Set(r.buildKey(key), data, r.cfg.Cache.DefaultExpiration).Err()
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
+
+// GetString returns an string from cache
+func (r *RedisCache) GetString(key string) (data string, err error) {
+ val, err := r.GetItem(key)
+ if err == domain.ErrCacheMiss {
+ return data, domain.ErrCacheMiss
+ } else if err != nil {
+ return data, errors.Wrap(err)
+ }
+
+ return string(val), nil
+}
+
+// SetString sets an item in cache
+func (r *RedisCache) SetString(key string, data string) error {
+ err := r.SetItem(key, []byte(data))
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
+
+// GetStruct returns an struct from cache
+func (r *RedisCache) GetStruct(key string, data interface{}) (err error) {
+ val, err := r.GetItem(key)
+ if err == domain.ErrCacheMiss {
+ return domain.ErrCacheMiss
+ } else if err != nil {
+ return errors.Wrap(err)
+ }
+
+ err = json.Unmarshal(val, &data)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
+
+// SetStruct sets an item in cache
+func (r *RedisCache) SetStruct(key string, data interface{}) error {
+ dataString, err := json.Marshal(data)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ err = r.SetItem(key, dataString)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
+
+// GetExpiration returns the expiration time for a key
+func (r *RedisCache) GetExpiration(key string) (expiration time.Duration, err error) {
+ expiration, err = r.redis.TTL(r.buildKey(key)).Result()
+ if err != nil {
+ return expiration, errors.Wrap(err)
+ }
+
+ return expiration, nil
+}
+
+// SetExpiration sets the expiration time for a key
+func (r *RedisCache) SetExpiration(key string, expiration time.Duration) (err error) {
+ err = r.redis.Expire(r.buildKey(key), expiration).Err()
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
diff --git a/infra/config/config.go b/infra/config/config.go
new file mode 100644
index 0000000..2497985
--- /dev/null
+++ b/infra/config/config.go
@@ -0,0 +1,249 @@
+package config
+
+import (
+ "strings"
+
+ "os"
+
+ "time"
+
+ "github.com/spf13/viper"
+)
+
+// Config represents the configuration values for the whole service.
+type Config struct {
+ App AppConfig
+ DB DBConfig
+ HTTP HTTPConfig
+ Log LogConfig
+ Aws AwsConfig
+ Cache CacheConfig
+ Twilio TwilioConfig
+ Lyft LyftConfig
+ LyftProd LyftProdConfig
+ BXE BXEConfig
+ Blue365 Blue365Config
+ Email EmailConfig
+ GoogleShortener GoogleShortenerConfig
+}
+
+// AppConfig represents the configuration values about the application.
+type AppConfig struct {
+ Name string
+ Debug bool
+ Docs DocsConfig
+}
+
+// TwilioConfig represents the configuration values about the twilio.
+type TwilioConfig struct {
+ Account string
+ Token string
+ Sender string
+ TwiMLSID string
+}
+
+// LyftConfig represents the configuration values about the lyft.
+type LyftConfig struct {
+ Client string
+ Secret string
+ RefreshToken string
+}
+
+type LyftProdConfig struct {
+ Lyft LyftConfig
+ UserUUID string
+}
+
+// BXEConfig represents the configuration values about the BXE.
+type BXEConfig struct {
+ URL string
+ APIKey string
+ Secret string
+}
+
+// Blue365Config represents the configuration values about the Blue 365.
+type Blue365Config struct {
+ URL string
+ APIKey string
+ Secret string
+}
+
+// DBConfig represents the configuration values about the DB.
+type DBConfig struct {
+ User string
+ Pass string
+ Name string
+ Host string
+ Port int
+ MaxLifeInMinutes int
+ MaxIdleConns int
+ MaxOpenConns int
+}
+
+// HTTPConfig represents the configuration values about the HTTP server.
+type HTTPConfig struct {
+ Port int
+ Prefix string
+ Auth HTTPAuthConfig
+}
+
+// HTTPAuthConfig represents the configuration values about the HTTP authentication (JWT and CORS).
+type HTTPAuthConfig struct {
+ AppKey string
+ CertificatePath string
+ FrontendURLs []string
+}
+
+// LogConfig represents the configuration values about the logging config.
+type LogConfig struct {
+ LogToFile bool
+ Path string
+}
+
+// AwsConfig represents the configuration values about the aws config.
+type AwsConfig struct {
+ S3Bucket string
+}
+
+// DocsConfig represents the configuration values about the documentation config.
+type DocsConfig struct {
+ YAMLPath string
+ SwaggerPath string
+}
+
+// CacheConfig represents the configuration values about the documentation config.
+type CacheConfig struct {
+ Server string
+ Port int
+ DB int
+ Pass string
+ Prefix string
+ DefaultExpiration time.Duration
+}
+
+// CacheConfig represents the configuration values about the documentation config.
+type EmailConfig struct {
+ Server string
+ Port int
+ User string
+ Pass string
+ Sender string
+}
+
+type GoogleShortenerConfig struct {
+ APIKey string
+ ClientID string
+ SecretKey string
+}
+
+// Read returns the configuration values,
+// based on the configuration files and environment variables.
+func Read() (*Config, error) {
+ setup()
+ err := viper.ReadInConfig()
+ if err != nil {
+ if err == os.ErrNotExist {
+ viper.SetConfigName("config.local")
+ err = viper.ReadInConfig()
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &Config{
+ App: AppConfig{
+ Name: viper.GetString("app.name"),
+ Debug: viper.GetBool("app.debug"),
+ Docs: DocsConfig{
+ YAMLPath: viper.GetString("app.docs.yaml-path"),
+ SwaggerPath: viper.GetString("app.docs.swagger-path"),
+ },
+ },
+ DB: DBConfig{
+ User: viper.GetString("db.user"),
+ Pass: viper.GetString("db.pass"),
+ Name: viper.GetString("db.name"),
+ Host: viper.GetString("db.host"),
+ Port: viper.GetInt("db.port"),
+ MaxLifeInMinutes: viper.GetInt("db.max-life-minutes"),
+ MaxIdleConns: viper.GetInt("db.max-idle-conns"),
+ MaxOpenConns: viper.GetInt("db.max-open-conns"),
+ },
+ HTTP: HTTPConfig{
+ Port: viper.GetInt("http.port"),
+ Prefix: viper.GetString("http.prefix"),
+ Auth: HTTPAuthConfig{
+ AppKey: viper.GetString("http.auth.app-key"),
+ CertificatePath: viper.GetString("http.auth.certificate-path"),
+ FrontendURLs: viper.GetStringSlice("http.auth.frontend-urls"),
+ },
+ },
+ Log: LogConfig{
+ LogToFile: viper.GetBool("log.log-to-file"),
+ Path: viper.GetString("log.path"),
+ },
+ Aws: AwsConfig{
+ S3Bucket: viper.GetString("aws.s3-bucket"),
+ },
+ Cache: CacheConfig{
+ Server: viper.GetString("cache.server"),
+ Port: viper.GetInt("cache.port"),
+ DB: viper.GetInt("cache.db"),
+ Pass: viper.GetString("cache.pass"),
+ Prefix: viper.GetString("cache.prefix"),
+ DefaultExpiration: viper.GetDuration("cache.default-expiration"),
+ },
+ Lyft: LyftConfig{
+ Client: viper.GetString("lyft.key"),
+ Secret: viper.GetString("lyft.secret"),
+ RefreshToken: viper.GetString("lyft.token"),
+ },
+ LyftProd: LyftProdConfig{
+ Lyft: LyftConfig{
+ Client: viper.GetString("lyft-prod.key"),
+ Secret: viper.GetString("lyft-prod.secret"),
+ RefreshToken: viper.GetString("lyft-prod.token"),
+ },
+ UserUUID: viper.GetString("lyft-prod.user-uuid"),
+ },
+ Twilio: TwilioConfig{
+ Account: viper.GetString("twilio.account"),
+ Token: viper.GetString("twilio.token"),
+ Sender: viper.GetString("twilio.sender"),
+ TwiMLSID: viper.GetString("twilio.twiml-sid"),
+ },
+ BXE: BXEConfig{
+ URL: viper.GetString("bxe.url"),
+ APIKey: viper.GetString("bxe.key"),
+ Secret: viper.GetString("bxe.secret"),
+ },
+ Blue365: Blue365Config{
+ URL: viper.GetString("blue365.url"),
+ APIKey: viper.GetString("blue365.key"),
+ Secret: viper.GetString("blue365.secret"),
+ },
+ Email: EmailConfig{
+ Server: viper.GetString("email.server"),
+ Port: viper.GetInt("email.port"),
+ User: viper.GetString("email.user"),
+ Pass: viper.GetString("email.pass"),
+ Sender: viper.GetString("email.sender"),
+ },
+ GoogleShortener: GoogleShortenerConfig{
+ APIKey: viper.GetString("google-shortener.api-key"),
+ ClientID: viper.GetString("google-shortener.client-id"),
+ SecretKey: viper.GetString("google-shortener.secret-key"),
+ },
+ }, nil
+}
+
+func setup() {
+ viper.SetEnvPrefix("api")
+ viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
+ viper.AutomaticEnv()
+
+ viper.SetConfigName("config")
+ viper.AddConfigPath(".")
+}
diff --git a/infra/errors/errors.go b/infra/errors/errors.go
new file mode 100644
index 0000000..97684b6
--- /dev/null
+++ b/infra/errors/errors.go
@@ -0,0 +1,177 @@
+package errors
+
+import (
+ "fmt"
+ "net/http"
+ "runtime"
+ "strings"
+)
+
+type errorWrapper interface {
+ Error() string
+ GetOriginalError() *error
+}
+
+// WrappedError holds an error wrapped with a context message
+type WrappedError struct {
+ originalError *error
+ path string
+ messages []string
+}
+
+func (err WrappedError) Error() string {
+ if len(err.messages) > 0 {
+ retVal := fmt.Sprintf("%s: ", err.path)
+
+ for _, message := range err.messages {
+ retVal += message + "; "
+ }
+
+ return fmt.Sprintf("%s => %v", retVal, *err.originalError)
+ }
+
+ return fmt.Sprintf("%s => %v", err.path, *err.originalError)
+}
+
+// GetOriginalError returns the original error
+func (err WrappedError) GetOriginalError() *error {
+ if err.originalError != nil {
+ if originalError, ok := (*err.originalError).(errorWrapper); ok {
+ return originalError.GetOriginalError()
+ }
+ }
+
+ return err.originalError
+}
+
+// Wrap wraps an error with a context message
+func Wrap(err error, messages ...string) error {
+ if err != nil {
+ // get caller function path
+ pc := make([]uintptr, 10)
+ runtime.Callers(2, pc)
+ funcRef := runtime.FuncForPC(pc[0])
+
+ pathArr := strings.Split(funcRef.Name(), "/")
+
+ path := pathArr[len(pathArr)-1]
+
+ return &WrappedError{
+ originalError: &err,
+ path: path,
+ messages: messages,
+ }
+ }
+
+ return nil
+}
+
+// NewValidationError returns a ValidationError instance with the provided parameters
+func NewValidationError(field string, message string) *ValidationError {
+ return &ValidationError{
+ Field: field,
+ Message: message,
+ }
+}
+
+// NewNullArgumentError returns a preformatted error for null arguments
+func NewNullArgumentError(argumentName string) *NullArgumentError {
+ return &NullArgumentError{argumentName}
+}
+
+// NewApplicationError returns a ApplicationError instance
+func NewApplicationError(path string, message string) *ApplicationError {
+ return &ApplicationError{
+ Message: message,
+ Path: path,
+ }
+}
+
+// NewNotAuthorizedError returns a NotAuthorizedError instance
+func NewNotAuthorizedError(message string) *NotAuthorizedError {
+ return &NotAuthorizedError{
+ Message: message,
+ }
+}
+
+// NewHTTPError returns a HTTPError instance
+func NewHTTPError(httpStatus int, message string) *HTTPError {
+ return &HTTPError{
+ Status: httpStatus,
+ Message: message,
+ }
+}
+
+// NewNotFoundError returns a Not Found HTTPError instance
+func NewNotFoundError() *HTTPError {
+ return NewHTTPError(http.StatusNotFound, "Not Found")
+}
+
+// HTTPError represents a generic HTTP error response
+type HTTPError struct {
+ Status int
+ Message string
+}
+
+func (e *HTTPError) Error() string {
+ return fmt.Sprintf("%v - %s", e.Status, e.Message)
+}
+
+// NullArgumentError represents a error that is used to sinalize that a provided argument is null
+type NullArgumentError struct {
+ ArgumentName string
+}
+
+func (e *NullArgumentError) Error() string {
+ return fmt.Sprintf("Parameter %s can't be null", e.ArgumentName)
+}
+
+// ValidationError represents an input validation error
+type ValidationError struct {
+ Field string `json:"field_name,omitempty"`
+ Message string `json:"message,omitempty"`
+ Errors []ValidationError `json:"errors,omitempty"`
+}
+
+func (e *ValidationError) Error() string {
+ var errorList []string
+
+ for _, err := range e.Errors {
+ errorList = append(errorList, err.Error())
+ }
+
+ output := e.Message
+
+ if len(errorList) > 0 {
+ output += fmt.Sprintf("\n - %v", strings.Join(errorList, ";\n - "))
+ }
+
+ return fmt.Sprintf("%v: %v", e.Field, output)
+}
+
+// AddError adds a new validation error to the chain
+func (e *ValidationError) AddError(field string, message string) {
+ e.Errors = append(e.Errors, ValidationError{
+ Field: field,
+ Message: message,
+ })
+}
+
+// ApplicationError represents a common applicatino error structure
+type ApplicationError struct {
+ Message string
+ Path string
+}
+
+func (e *ApplicationError) Error() string {
+ return e.Message
+}
+
+// NotAuthorizedError represents an access restriction error structure
+type NotAuthorizedError struct {
+ Message string
+}
+
+func (e *NotAuthorizedError) Error() string {
+ return e.Message
+}
diff --git a/infra/logger/logger.go b/infra/logger/logger.go
new file mode 100644
index 0000000..872db20
--- /dev/null
+++ b/infra/logger/logger.go
@@ -0,0 +1,53 @@
+package logger
+
+import (
+ "fmt"
+ "os"
+
+ "io"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/Sirupsen/logrus"
+)
+
+// Logger is the default application logger compatible with the echo.Logger interface
+type Logger struct {
+ cfg *config.Config
+ *logrus.Entry
+}
+
+// InfoWriter returns the io.Writer for info level
+func (l *Logger) InfoWriter() io.Writer {
+ return l.WriterLevel(logrus.InfoLevel)
+}
+
+// ErrorWriter returns the io.Writer for error level
+func (l *Logger) ErrorWriter() io.Writer {
+ return l.WriterLevel(logrus.ErrorLevel)
+}
+
+// New returns a new Logger instance
+func New(cfg *config.Config) (*Logger, error) {
+ if cfg.Log.LogToFile {
+ file, err := os.Create(cfg.Log.Path)
+ if err != nil {
+ fmt.Printf("Error to create log file for library: %s\n", err.Error())
+ panic(err)
+ }
+ logrus.SetOutput(file)
+ }
+
+ logrus.SetFormatter(&logrus.JSONFormatter{})
+
+ if cfg.App.Debug {
+ logrus.SetLevel(logrus.DebugLevel)
+ } else {
+ logrus.SetLevel(logrus.InfoLevel)
+ }
+
+ entry := logrus.WithFields(logrus.Fields{
+ "app": cfg.App.Name,
+ })
+
+ return &Logger{cfg, entry}, nil
+}
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..9e28fed
--- /dev/null
+++ b/main.go
@@ -0,0 +1,66 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/signal"
+ "time"
+
+ "io"
+
+ "bitbucket.org/nemt/nemt-portal-api/data"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/cache"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/logger"
+ "bitbucket.org/nemt/nemt-portal-api/server"
+)
+
+func main() {
+ var err error
+
+ cfg, err := config.Read()
+ endAsErr(err, "Could not read configuration file.", os.Stdout, os.Stderr)
+
+ log, err := logger.New(cfg)
+ endAsErr(err, "Could not create logging structure.", os.Stdout, os.Stderr)
+
+ log.Printf("Connecting to the database at %s:%d.\n", cfg.DB.Host, cfg.DB.Port)
+ db, err := data.Connect(cfg)
+ endAsErr(err, "Could not connect to database.", log.InfoWriter(), log.ErrorWriter())
+ atInterruption(func() {
+ log.Printf("Closing DB Connection.")
+ db.Close()
+ })
+
+ log.Printf("Connecting to the cache server at %s:%d.\n", cfg.Cache.Server, cfg.Cache.Port)
+ cache := cache.Instance(cfg)
+
+ svc, err := service.New(db, cache, cfg, log)
+ endAsErr(err, "Could not create service structure.", log.InfoWriter(), log.ErrorWriter())
+
+ // Runs server.
+ log.Info("Runninng server at localhost:", cfg.HTTP.Port)
+ err = server.Instance(svc, cfg, log, cache).Run()
+ endAsErr(err, "Could not start the server.", log.InfoWriter(), log.ErrorWriter())
+}
+
+func atInterruption(fn func()) {
+ go func() {
+ sc := make(chan os.Signal, 1)
+ signal.Notify(sc, os.Interrupt)
+ <-sc
+
+ fn()
+ os.Exit(0)
+ }()
+}
+
+func endAsErr(err error, message string, infow io.Writer, errorw io.Writer) {
+ if err != nil {
+ fmt.Fprintln(errorw, "Error:", err)
+ fmt.Fprintln(infow, message)
+ time.Sleep(time.Millisecond * 50) // needed for printing all messages before exiting
+ os.Exit(1)
+ }
+}
diff --git a/server/router/authenticateroute/controller.go b/server/router/authenticateroute/controller.go
new file mode 100644
index 0000000..c0d223c
--- /dev/null
+++ b/server/router/authenticateroute/controller.go
@@ -0,0 +1,125 @@
+package authenticateroute
+
+import (
+ "sync"
+ "time"
+
+ b64 "encoding/base64"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ }
+ })
+ return instance
+}
+
+func (c *controller) handlePortal(ctx echo.Context) error {
+ err := auth.ValidateAppKey(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ var user viewmodel.User
+ if err = ctx.Bind(&user); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if user.Email == nil || len(*user.Email) == 0 || len(user.Pass) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "email and pass are required", false)
+ }
+
+ pass, err := b64.StdEncoding.DecodeString(user.Pass)
+ if err != nil {
+ return routeutils.ResponseAPIAuthError(ctx, "Invalid email or password", false)
+ }
+ user.Pass = string(pass)
+
+ user, err = c.svc.Users.FullLogin("email", *user.Email, user.Pass, "SP")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if user.ID == "" {
+ return routeutils.ResponseAPIAuthError(ctx, "Invalid email or password", false)
+ }
+
+ token, err := auth.GenerateToken(c.cfg, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ response := viewmodel.AuthResponse{
+ Token: token,
+ ServerTime: time.Now().Unix(),
+ ValidTime: time.Now().Add(auth.TokenExpiration).Unix(),
+ User: user,
+ }
+
+ return routeutils.ResponseAPIOK(ctx, response)
+}
+
+func (c *controller) handleMember(ctx echo.Context) error {
+ err := auth.ValidateAppKey(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ var user viewmodel.User
+ if err = ctx.Bind(&user); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if user.PhoneNumber == nil || len(*user.PhoneNumber) == 0 || len(user.Pass) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "phonenumber and pass are required", false)
+ }
+
+ pass, err := b64.StdEncoding.DecodeString(user.Pass)
+ if err != nil {
+ return routeutils.ResponseAPIAuthError(ctx, "Invalid phonenumber or password", false)
+ }
+ user.Pass = string(pass)
+
+ user, err = c.svc.Users.FullLogin("phone_number", *user.PhoneNumber, user.Pass, "US")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if user.ID == "" {
+ return routeutils.ResponseAPIAuthError(ctx, "Invalid phonenumber or password", false)
+ }
+
+ token, err := auth.GenerateToken(c.cfg, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ response := viewmodel.AuthResponse{
+ Token: token,
+ ServerTime: time.Now().Unix(),
+ ValidTime: time.Now().Add(auth.TokenExpiration).Unix(),
+ User: user,
+ }
+
+ return routeutils.ResponseAPIOK(ctx, response)
+}
diff --git a/server/router/authenticateroute/router.go b/server/router/authenticateroute/router.go
new file mode 100644
index 0000000..88df89b
--- /dev/null
+++ b/server/router/authenticateroute/router.go
@@ -0,0 +1,20 @@
+package authenticateroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ portalRoute = "/portal"
+ memberRoute = "/member"
+)
+
+// Register authenticate route
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(cfg, svc)
+
+ r.POST(portalRoute, ctrl.handlePortal)
+ r.POST(memberRoute, ctrl.handleMember)
+}
diff --git a/server/router/docsroute/router.go b/server/router/docsroute/router.go
new file mode 100644
index 0000000..46eb195
--- /dev/null
+++ b/server/router/docsroute/router.go
@@ -0,0 +1,17 @@
+package docsroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = "/"
+ yamlRoute = "/yaml"
+)
+
+// Register registers the handlers for doc routes
+func Register(r *echo.Group, cfg *config.Config) {
+ r.Static(yamlRoute, cfg.App.Docs.YAMLPath)
+ r.Static(rootRoute, cfg.App.Docs.SwaggerPath)
+}
diff --git a/server/router/eligibilityroute/controller.go b/server/router/eligibilityroute/controller.go
new file mode 100644
index 0000000..0bf4c3a
--- /dev/null
+++ b/server/router/eligibilityroute/controller.go
@@ -0,0 +1,49 @@
+package eligibilityroute
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ bcbsi *bcbsi.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ bcbsi: bcbsi.New(cfg),
+ }
+ })
+ return instance
+}
+
+func (c *controller) handleEligibility(ctx echo.Context) error {
+ var eligibility viewmodel.Eligibility
+
+ if err := ctx.Bind(&eligibility); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ret, err := c.bcbsi.BXE.CheckEligibility(eligibility)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, ret)
+}
diff --git a/server/router/eligibilityroute/router.go b/server/router/eligibilityroute/router.go
new file mode 100644
index 0000000..da302e7
--- /dev/null
+++ b/server/router/eligibilityroute/router.go
@@ -0,0 +1,17 @@
+package eligibilityroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+)
+
+// Register authenticate route
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(cfg, svc)
+ r.POST(rootRoute, ctrl.handleEligibility)
+}
diff --git a/server/router/externalroute/controller.go b/server/router/externalroute/controller.go
new file mode 100644
index 0000000..cf2628c
--- /dev/null
+++ b/server/router/externalroute/controller.go
@@ -0,0 +1,290 @@
+package externalroute
+
+import (
+ "fmt"
+ "strings"
+ "sync"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ tnc *tncservice.Service
+ notification *notificationservice.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ tnc: tnc,
+ notification: notification,
+ }
+ })
+ return instance
+}
+
+func (c *controller) getDriverNotification(ride viewmodel.Ride, notificationType string, subject string, message string, to string, from string) viewmodel.Notification {
+ retVal := viewmodel.Notification{
+ Type: notificationType,
+ Message: message,
+ Subject: subject,
+ Ride: ride,
+ User: ride.User,
+ CreatedUser: ride.CreatedUser,
+ To: to,
+ From: from,
+ }
+
+ return retVal
+}
+
+func (c *controller) handleCancel(ctx echo.Context) error {
+ var rideUUID = ctx.Param("ride_uuid")
+ var userUUID = ctx.Param("user_uuid")
+
+ ride, err := c.svc.Rides.GetByUUIDAndUserUUID(rideUUID, userUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ lyftRide := viewmodel.RideRequest{RideID: ride.InternalID}
+ if ride.Status.Key == "scheduled" && !strings.Contains(ride.InternalID, "s_") {
+ lyftRide.RideID = "s_" + ride.InternalID
+ }
+
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ if err = c.tnc.Lyft.CancelRide(lyftRide); err != nil {
+ if err.Error() != "ride_not_found" {
+ fmt.Println("Error to cancel with Lyft: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ }
+ } else {
+ fmt.Println("In Production")
+ if err = c.tnc.LyftProd.CancelRide(lyftRide); err != nil {
+ fmt.Println("Error to cancel with Lyft: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ }
+
+ err = c.svc.Rides.UpdateStatus(rideUUID, "canceled")
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ // ride.Status.Key = "canceled"
+
+ // err = c.svc.Notification.SendNotification(ride.Status.Key, ride, viewmodel.RideRequest{})
+ // if err != nil {
+ // fmt.Println("Error to notify: ", err.Error())
+ // }
+
+ ctx.Response().Header().Set("Content-Type", "application/json")
+ return routeutils.ResponseNoContent(ctx, nil)
+}
+
+func (c *controller) handleMessage(ctx echo.Context) error {
+ var rideUUID = ctx.Param("ride_uuid")
+ var userUUID = ctx.Param("user_uuid")
+
+ ride, err := c.svc.Rides.GetByUUIDAndUserUUID(rideUUID, userUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ message := make(map[string]string)
+ err = ctx.Bind(&message)
+ if err != nil || message["message"] == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "message body param is mandatory")
+ }
+
+ if err != nil || message["to"] == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "to param is mandatory")
+ }
+ notifications := make([]viewmodel.Notification, 0)
+ if message["to"] == "driver" {
+ notifications = append(notifications, c.getDriverNotification(ride, "sms", "A message to driver", message["message"], ride.Driver.PhoneNumber, *ride.User.PhoneNumber))
+ } else {
+ notifications = append(notifications, c.getDriverNotification(ride, "sms", "A message to dispatcher", message["message"], *ride.CreatedUser.PhoneNumber, *ride.User.PhoneNumber))
+ notifications = append(notifications, c.getDriverNotification(ride, "email", "A message to dispatcher", message["message"], *ride.CreatedUser.Email, *ride.User.Email))
+ }
+
+ notifications, err = c.svc.Notification.SendNotifications(notifications)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, notifications)
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ var rideUUID = ctx.Param("ride_uuid")
+ var userUUID = ctx.Param("user_uuid")
+
+ ride, err := c.svc.Rides.GetByUUIDAndUserUUID(rideUUID, userUUID)
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
+ var lyftRide viewmodel.RideRequest
+ var err error
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ }
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride.Route.Location = ride.Route.Origin
+ ride.Route.Location.Address = ""
+ ride.Route.Location.Name = ""
+
+ switch ride.Status.Key {
+ case "accepted":
+ if lyftRide.Origin.ETASeconds != nil {
+ ride.Route.ETA = *lyftRide.Origin.ETASeconds
+ } else {
+ ride.Route.ETA = 0
+ if c.cfg.App.Debug {
+ ride.Route.ETA = 350
+ }
+ }
+ case "pickedUp":
+ case "arrived":
+ if lyftRide.Destination.ETASeconds != nil {
+ ride.Route.ETA = *lyftRide.Destination.ETASeconds
+ } else {
+ ride.Route.ETA = 0
+ if c.cfg.App.Debug {
+ ride.Route.ETA = 350
+ }
+ }
+ }
+
+ if lyftRide.Location.Latitude != 0 && lyftRide.Location.Longitude != 0 {
+ ride.Route.Location.Latitude = lyftRide.Location.Latitude
+ ride.Route.Location.Longitude = lyftRide.Location.Longitude
+ ride.Route.Location.Bearing = lyftRide.Location.Bearing
+ }
+ }
+
+ ride.InternalID = ""
+ ride.User.Gender = nil
+ ride.User.Email = nil
+ ride.User.PhoneNumber = nil
+ ride.Passenger = viewmodel.UserLyft{}
+ // ride.Visit = viewmodel.Visit{
+ // ExternalID: ride.Visit.ExternalID,
+ // }
+ ride.CreatedUser = viewmodel.User{}
+
+ return routeutils.ResponseAPIOK(ctx, ride)
+}
+
+func (c *controller) handleReady(ctx echo.Context) error {
+ var rideUUID = ctx.Param("ride_uuid")
+ var userUUID = ctx.Param("user_uuid")
+
+ ride, err := c.svc.Rides.GetByUUIDAndUserUUID(rideUUID, userUUID)
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ authUser, err := c.svc.Users.GetByUUID(ride.CreatedUser.ID, "")
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ var nextRide viewmodel.Ride
+ if ride.TripType.Key == "from_visit_call" && ride.Status.Key == "willCall" {
+ nextRide = ride
+ } else if ride.Visit.TripType.Key == "roundtrip_call" && ride.TripType.Key == "to_visit" {
+ roundTripRide, err := c.svc.Rides.GetByVisitUUIDAndTripType(ride.Visit.UUID, "from_visit_call", authUser)
+ if err != nil {
+ fmt.Println("Error to get next ride: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ nextRide = roundTripRide
+ } else {
+ fmt.Println("Error on get next ride ")
+ return routeutils.ResponseAPINotFoundError(ctx)
+ }
+
+ var lyftRide viewmodel.RideRequest
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ }
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ lyftRide.RideID = ""
+ lyftRide.Destination = ride.Route.Destination
+ lyftRide.Origin = ride.Route.Origin
+
+ name := nextRide.User.Name
+ names := strings.Split(name, " ")
+ lyftRide.Passenger.FirstName = names[0]
+ lyftRide.Passenger.LastName = " "
+ lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
+ lyftRide.RideType = "lyft"
+
+ if c.cfg.LyftProd.UserUUID != nextRide.CreatedUser.ID {
+ lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.RequestRide(lyftRide)
+ }
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ currentTime := time.Now()
+ lyftRide.PickupTime = ¤tTime
+ lyftRide.ReturnTime = ¤tTime
+ nextRide.PickupTime = ¤tTime
+
+ nextRide, err = c.svc.Rides.UpdateNewRide(nextRide, lyftRide, authUser)
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ go func() {
+ err = c.svc.Notification.SendNotification(lyftRide.Status, nextRide, lyftRide)
+ if err != nil {
+ fmt.Println("Error to notify user: ", err.Error())
+ }
+ }()
+
+ return routeutils.ResponseAPIOK(ctx, nextRide)
+}
diff --git a/server/router/externalroute/router.go b/server/router/externalroute/router.go
new file mode 100644
index 0000000..6080d0b
--- /dev/null
+++ b/server/router/externalroute/router.go
@@ -0,0 +1,25 @@
+package externalroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = "/:ride_uuid/:user_uuid"
+ cancelRoute = "/:ride_uuid/:user_uuid/cancel"
+ messageRoute = "/:ride_uuid/:user_uuid/message"
+ readyRoute = "/:ride_uuid/:user_uuid/ready"
+)
+
+// Register authenticate route
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) {
+ ctrl := controllerInstance(cfg, svc, tnc, notification)
+ r.GET(rootRoute, ctrl.handle)
+ r.PUT(cancelRoute, ctrl.handleCancel)
+ r.POST(messageRoute, ctrl.handleMessage)
+ r.POST(readyRoute, ctrl.handleReady)
+}
diff --git a/server/router/healthroute/controller.go b/server/router/healthroute/controller.go
new file mode 100644
index 0000000..05af52c
--- /dev/null
+++ b/server/router/healthroute/controller.go
@@ -0,0 +1,27 @@
+package healthroute
+
+import (
+ "net/http"
+ "sync"
+
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+}
+
+func controllerInstance() *controller {
+ once.Do(func() {
+ instance = &controller{}
+ })
+ return instance
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ return ctx.String(http.StatusOK, "OK")
+}
diff --git a/server/router/healthroute/router.go b/server/router/healthroute/router.go
new file mode 100644
index 0000000..816e450
--- /dev/null
+++ b/server/router/healthroute/router.go
@@ -0,0 +1,15 @@
+package healthroute
+
+import (
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = "/"
+)
+
+func Register(r *echo.Group) {
+ ctrl := controllerInstance()
+
+ r.GET(rootRoute, ctrl.handle)
+}
diff --git a/server/router/lyfthookroute/controller.go b/server/router/lyfthookroute/controller.go
new file mode 100644
index 0000000..df15fc5
--- /dev/null
+++ b/server/router/lyfthookroute/controller.go
@@ -0,0 +1,193 @@
+package lyfthookroute
+
+import (
+ "fmt"
+ "io/ioutil"
+ "strings"
+ "sync"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+ "github.com/pquerna/ffjson/ffjson"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ tnc *tncservice.Service
+ notification *notificationservice.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ tnc: tnc,
+ notification: notification,
+ }
+ })
+ return instance
+}
+
+func (c *controller) handleStateChange(ctx echo.Context) error {
+ var rideUUID = ctx.Param("ride_uuid")
+ var status = ctx.Param("status")
+
+ user, err := c.svc.Users.GetByUUID("573c70ff-733d-11e7-ba8f-0a6ad3fcdeaa", "")
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideUUID, user)
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ // var lyftRide viewmodel.RideRequest
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ _, err = c.tnc.Lyft.GetRideStatus(viewmodel.RideRequest{RideID: ride.InternalID}, status)
+ go func() {
+ secondCall := func() {
+ ride.InternalID = "s_" + ride.InternalID
+ c.tnc.Lyft.GetRideStatus(viewmodel.RideRequest{RideID: ride.InternalID}, status)
+ }
+ time.AfterFunc(1*time.Second, secondCall)
+ }()
+ } else {
+ _, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ }
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ // if ride.Route.ETA ==
+
+ // UUID, _ := uuid.NewV4()
+ // hook := viewmodel.WebhookResponse{
+ // Event: lyftRide,
+ // EventID: UUID.String(),
+ // EventType: "ride.status.updated",
+ // HREF: "Test",
+ // OccurredAt: time.Now().UTC().Format("2006-01-02T15:04:05-0700"),
+ // }
+
+ // ride, err = c.svc.Rides.Update(hook)
+ // if err != nil {
+ // fmt.Println("Error: ", err.Error())
+ // return routeutils.HandleAPIError(ctx, err)
+ // }
+
+ // lyftRide.Driver.FirstName = ride.Driver.FirstName
+ // lyftRide.Driver.LastName = ride.Driver.LastName
+ // lyftRide.Status = ride.Status.Key
+ // lyftRide.Vehicle.Color = ride.Vehicle.Color
+ // lyftRide.Vehicle.LicensePlate = ride.Vehicle.LicensePlate
+ // lyftRide.Vehicle.Make = ride.Vehicle.Make
+ // lyftRide.Vehicle.Model = ride.Vehicle.Model
+ // lyftRide.Destination.ETASeconds = &ride.Route.ETA
+ // if lyftRide.Status == "canceled" {
+ // lyftRide.CanceledBy = "driver"
+ // }
+
+ // if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
+ // ride.Route.Location = ride.Route.Origin
+ // ride.Route.Location.Address = ""
+ // ride.Route.Location.Name = ""
+
+ // switch ride.Status.Key {
+ // case "accepted":
+ // if lyftRide.Origin.ETASeconds != nil {
+ // ride.Route.ETA = *lyftRide.Origin.ETASeconds
+ // } else {
+ // ride.Route.ETA = 0
+ // if c.cfg.App.Debug {
+ // ride.Route.ETA = 350
+ // }
+ // }
+ // case "pickedUp":
+ // case "arrived":
+ // if lyftRide.Destination.ETASeconds != nil {
+ // ride.Route.ETA = *lyftRide.Destination.ETASeconds
+ // } else {
+ // ride.Route.ETA = 0
+ // if c.cfg.App.Debug {
+ // ride.Route.ETA = 350
+ // }
+ // }
+ // }
+
+ // if lyftRide.Location.Latitude != 0 && lyftRide.Location.Longitude != 0 {
+ // ride.Route.Location.Latitude = lyftRide.Location.Latitude
+ // ride.Route.Location.Longitude = lyftRide.Location.Longitude
+ // ride.Route.Location.Bearing = lyftRide.Location.Bearing
+ // }
+ // }
+
+ // err = c.svc.Notification.SendNotification(status, ride, lyftRide)
+ // if err != nil {
+ // fmt.Println("Error: ", err.Error())
+ // return routeutils.HandleAPIError(ctx, err)
+ // }
+
+ return routeutils.ResponseAPIOK(ctx, ride)
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ fmt.Println("RECEIVING HOOK: ")
+ body, err := ioutil.ReadAll(ctx.Request().Body)
+ if err != nil {
+ fmt.Println("Error to read the body of the webhook: ", err.Error())
+ } else {
+ fmt.Println(string(body))
+ }
+
+ var requestRide viewmodel.WebhookResponse
+ err = ffjson.Unmarshal(body, &requestRide)
+ if err != nil {
+ fmt.Println(err)
+ return routeutils.ResponseAPIValidationError(ctx, "invalid parameters")
+ }
+ defer ctx.Request().Body.Close()
+ // err = ctx.Bind(&requestRide)
+ // if err != nil {
+ // fmt.Println(err)
+ // return routeutils.ResponseAPIValidationError(ctx, "invalid parameters")
+ // }
+
+ requestRide.Event.RideID = strings.Replace(requestRide.Event.RideID, "s_", "", -1)
+ requestRide.Event.RideID = strings.Replace(requestRide.Event.RideID, "sandboxevent-", "", -1)
+
+ ride, err := c.svc.Rides.Update(requestRide)
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ switch requestRide.EventType {
+ case "ride.status.updated":
+ go func() {
+ if err := c.svc.Notification.SendNotification(requestRide.Event.Status, ride, requestRide.Event); err != nil {
+ fmt.Println("Error: ", err.Error())
+ }
+ }()
+ default:
+ fmt.Println(requestRide.EventType, " :", requestRide.Event.Status)
+ }
+
+ ctx.Response().Header().Set("Content-Type", "application/json")
+ return routeutils.ResponseAPIOK(ctx, ride)
+}
diff --git a/server/router/lyfthookroute/router.go b/server/router/lyfthookroute/router.go
new file mode 100644
index 0000000..56aecdc
--- /dev/null
+++ b/server/router/lyfthookroute/router.go
@@ -0,0 +1,26 @@
+package lyfthookroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+ stateChangeRoute = "/:ride_uuid/:status"
+)
+
+// Register authenticate route
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) {
+
+ ctrl := controllerInstance(cfg, svc, tnc, notification)
+
+ r.POST(rootRoute, ctrl.handle)
+
+ if cfg.App.Debug {
+ r.GET(stateChangeRoute, ctrl.handleStateChange)
+ }
+}
diff --git a/server/router/notificationroute/controller.go b/server/router/notificationroute/controller.go
new file mode 100644
index 0000000..f715991
--- /dev/null
+++ b/server/router/notificationroute/controller.go
@@ -0,0 +1,156 @@
+package notificationroute
+
+import (
+ "fmt"
+ "net/http"
+ "sync"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/gorilla/websocket"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+ upgrader = websocket.Upgrader{}
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ tnc *tncservice.Service
+ notification *notificationservice.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ tnc: tnc,
+ notification: notification,
+ }
+ })
+
+ upgrader = websocket.Upgrader{
+ CheckOrigin: func(r *http.Request) bool {
+ return true
+ },
+ EnableCompression: true,
+ Error: func(w http.ResponseWriter, r *http.Request, status int, reason error) {
+ fmt.Println("Error on websocket: ", status, " - ", reason)
+ },
+ }
+
+ go svc.Notification.DeliverMessage()
+
+ return instance
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ return routeutils.ResponseAPIOK(ctx, "OK")
+}
+
+func (c *controller) handleNotification(ctx echo.Context) error {
+ sRead := ctx.QueryParam("read")
+ isRead := (sRead == "true")
+
+ userUUID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "User ID is mandatory")
+ if err != nil {
+ return err
+ }
+
+ contactType, err := routeutils.GetAndValidateStringParam(ctx, "status", "User ID is mandatory")
+ if err != nil {
+ return err
+ }
+
+ n, err := c.svc.Notification.GetByUserUUIDAndReadStatus(viewmodel.User{ID: userUUID}, contactType, isRead)
+ if err != nil {
+ fmt.Println("Error to get notifications: ", err.Error())
+ }
+
+ return routeutils.ResponseAPIOK(ctx, n)
+}
+
+func (c *controller) handleSocket(ctx echo.Context) error {
+ ws, err := upgrader.Upgrade(ctx.Response(), ctx.Request(), nil)
+ if err != nil {
+ return err
+ }
+ defer ws.Close()
+
+ userUUID := ctx.QueryParam("id")
+ if userUUID == "" {
+ fmt.Println("User not found")
+ }
+
+ user, err := c.svc.Users.GetByUUID(userUUID, "SP")
+ if err != nil {
+ fmt.Println("User not found on our system: ", err.Error())
+ }
+
+ if user.ID == "" {
+ user, err = c.svc.Users.GetByUUID(userUUID, "US")
+ if err != nil {
+ fmt.Println("User not found on our system: ", err.Error())
+ }
+ }
+
+ _, err = c.svc.Notification.Subscribe(user, ws)
+ if err != nil {
+ fmt.Println("Error to subscribe user: ", err.Error())
+ }
+
+ n, err := c.svc.Notification.GetByUserUUIDAndReadStatus(user, "app", false)
+ if err != nil {
+ fmt.Println("Error to get notifications: ", err.Error())
+ }
+
+ loc, _ := time.LoadLocation("America/Chicago")
+ for _, i := range n {
+ m := viewmodel.Message{
+ DeliveryID: user.ID,
+ NotificationID: i.UUID,
+ CreateDate: i.Created.In(loc),
+ Read: i.Read,
+ Content: viewmodel.MessageContent{
+ Payload: i.Ride,
+ Subject: i.Subject,
+ Content: i.Message,
+ Type: i.MessageType,
+ },
+ }
+
+ if err := c.svc.Notification.SendMessage(m); err != nil {
+ fmt.Println("Error to send message: ", err.Error())
+ }
+ }
+
+ for {
+ var m viewmodel.Message
+ if err := ws.ReadJSON(&m); err != nil {
+ _, ok := err.(*websocket.CloseError)
+ if !ok {
+ fmt.Println("Error to read message: ", err.Error())
+ }
+ }
+
+ if m.Content.Type == "disable-notification" {
+ if err := c.svc.Notification.ReadStatus(m.NotificationID, true); err != nil {
+ fmt.Println("Error to disable notification: ", err.Error())
+ }
+ } else {
+ if err := c.svc.Notification.SendMessage(m); err != nil {
+ fmt.Println("Error to send message: ", err.Error())
+ }
+ }
+ }
+}
diff --git a/server/router/notificationroute/router.go b/server/router/notificationroute/router.go
new file mode 100644
index 0000000..693f9fc
--- /dev/null
+++ b/server/router/notificationroute/router.go
@@ -0,0 +1,25 @@
+package notificationroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+ userNotificationRoute = "/:user_uuid/:status"
+ webhookRoute = "/ws"
+)
+
+// Register authenticate route
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) {
+
+ ctrl := controllerInstance(cfg, svc, tnc, notification)
+
+ r.GET(rootRoute, ctrl.handle)
+ r.GET(webhookRoute, ctrl.handleSocket)
+ r.GET(userNotificationRoute, ctrl.handleNotification)
+}
diff --git a/server/router/organizationroute/controller.go b/server/router/organizationroute/controller.go
new file mode 100644
index 0000000..527ec09
--- /dev/null
+++ b/server/router/organizationroute/controller.go
@@ -0,0 +1,304 @@
+package organizationroute
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain"
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/cache"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ }
+ })
+
+ return instance
+}
+
+func (c *controller) handleTypes(ctx echo.Context) error {
+ cache := cache.Instance(c.cfg)
+ cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
+
+ resp := []viewmodel.OrganizationType{}
+ err := cache.GetStruct(cacheKey, &resp)
+ if err != nil {
+ if err != domain.ErrCacheMiss {
+ ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
+ }
+ resp, err = c.svc.Organization.GetAllTypes()
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ cache.SetStruct(cacheKey, resp)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleAddOrganization(ctx echo.Context) error {
+ var org viewmodel.Organization
+ err := ctx.Bind(&org)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ authUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ org.Author.ID = authUser.ID
+ org.LastEditor.ID = authUser.ID
+
+ resp, err := c.svc.Organization.AddOrganization(org, authUser)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ orgType, _ := routeutils.GetAndValidateStringQueryParam(ctx, "type", "Type is mandatory")
+
+ resp, err := c.svc.Organization.GetByType(orgType)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleDetail(ctx echo.Context) error {
+ orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Organization.GetByUUID(orgUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleParent(ctx echo.Context) error {
+ var parent viewmodel.Organization
+ err := ctx.Bind(&parent)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Organization.SetParentOrganization(orgUUID, parent.UUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleChild(ctx echo.Context) error {
+ var child viewmodel.Organization
+ err := ctx.Bind(&child)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ _, err = c.svc.Organization.SetParentOrganization(child.UUID, orgUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Organization.GetByUUID(orgUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleNameSearch(ctx echo.Context) error {
+ name, err := routeutils.GetAndValidateStringQueryParam(ctx, "name", "Name is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ searchType := ""
+ searchType, _ = routeutils.GetAndValidateStringQueryParam(ctx, "type", "Type is mandatory")
+
+ cache := cache.Instance(c.cfg)
+ cacheKey := ctx.Request().Method + ctx.Request().URL.RawPath + ctx.Request().URL.RawQuery
+
+ resp := []viewmodel.Organization{}
+ err = cache.GetStruct(cacheKey, &resp)
+ if err != nil {
+ if err != domain.ErrCacheMiss {
+ ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
+ }
+ resp, err = c.svc.Organization.GetByName(name, searchType)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ cache.SetStruct(cacheKey, resp)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleRemoveAddress(ctx echo.Context) error {
+ var address viewmodel.OrganizationAddress
+ err := ctx.Bind(&address)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ uInt, err := auth.GetTokenDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ createdUser := uInt.(map[string]interface{})
+ address.UpdatedUser.ID = createdUser["useruuid"].(string)
+
+ err = c.svc.Organization.InactivateOrganizationAddress(orgUUID, address)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Organization.GetByUUID(orgUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleAddAddress(ctx echo.Context) error {
+ var address viewmodel.OrganizationAddress
+ err := ctx.Bind(&address)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ uInt, err := auth.GetTokenDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ createdUser := uInt.(map[string]interface{})
+ address.CreatedUser.ID = createdUser["useruuid"].(string)
+ address.UpdatedUser.ID = address.CreatedUser.ID
+
+ _, err = c.svc.Organization.SetOrganizationAddress(orgUUID, address)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Organization.GetByUUID(orgUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleRemoveContact(ctx echo.Context) error {
+ var contact viewmodel.OrganizationContact
+ err := ctx.Bind(&contact)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ uInt, err := auth.GetTokenDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ createdUser := uInt.(map[string]interface{})
+ contact.UpdatedUser.ID = createdUser["useruuid"].(string)
+
+ err = c.svc.Organization.InactivateOrganizationContact(orgUUID, contact)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Organization.GetByUUID(orgUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleAddContact(ctx echo.Context) error {
+ var contact viewmodel.OrganizationContact
+ err := ctx.Bind(&contact)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ orgUUID, err := routeutils.GetAndValidateStringParam(ctx, "org_uuid", "Org ID is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ uInt, err := auth.GetTokenDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ createdUser := uInt.(map[string]interface{})
+ contact.CreatedUser.ID = createdUser["useruuid"].(string)
+ contact.UpdatedUser.ID = contact.CreatedUser.ID
+
+ _, err = c.svc.Organization.SetOrganizationContact(orgUUID, contact)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Organization.GetByUUID(orgUUID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
diff --git a/server/router/organizationroute/router.go b/server/router/organizationroute/router.go
new file mode 100644
index 0000000..ede6d99
--- /dev/null
+++ b/server/router/organizationroute/router.go
@@ -0,0 +1,39 @@
+package organizationroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+ detailRoute = "/:org_uuid"
+ parentRoute = "/:org_uuid/parent"
+ childRoute = "/:org_uuid/child"
+ addressRoute = "/:org_uuid/address"
+ contactRoute = "/:org_uuid/contact"
+ typeRoute = "/type"
+ nameRoute = "/name"
+)
+
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(cfg, svc)
+
+ r.GET(rootRoute, ctrl.handle)
+ r.POST(rootRoute, ctrl.handleAddOrganization)
+
+ r.GET(detailRoute, ctrl.handleDetail)
+
+ r.GET(typeRoute, ctrl.handleTypes)
+ r.GET(nameRoute, ctrl.handleNameSearch)
+
+ r.POST(parentRoute, ctrl.handleParent)
+ r.POST(childRoute, ctrl.handleChild)
+
+ r.POST(addressRoute, ctrl.handleAddAddress)
+ r.PUT(addressRoute, ctrl.handleRemoveAddress)
+
+ r.POST(contactRoute, ctrl.handleAddContact)
+ r.PUT(contactRoute, ctrl.handleRemoveContact)
+}
diff --git a/server/router/placesroute/controller.go b/server/router/placesroute/controller.go
new file mode 100644
index 0000000..3325736
--- /dev/null
+++ b/server/router/placesroute/controller.go
@@ -0,0 +1,55 @@
+package placesroute
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+ "golang.org/x/net/context"
+ "googlemaps.github.io/maps"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ maps *maps.Client
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
+ once.Do(func() {
+ c, _ := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ maps: c,
+ }
+ })
+
+ return instance
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ name, err := routeutils.GetAndValidateStringQueryParam(ctx, "name", "name is mandatory")
+ if err != nil {
+ return err
+ }
+
+ req := maps.PlaceAutocompleteRequest{
+ Input: name,
+ Language: "en",
+ }
+
+ resp, err := c.maps.PlaceAutocomplete(context.Background(), &req)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
diff --git a/server/router/placesroute/router.go b/server/router/placesroute/router.go
new file mode 100644
index 0000000..bc23af3
--- /dev/null
+++ b/server/router/placesroute/router.go
@@ -0,0 +1,17 @@
+package placesroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+)
+
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(cfg, svc)
+
+ r.GET(rootRoute, ctrl.handle)
+}
diff --git a/server/router/profileroute/controller.go b/server/router/profileroute/controller.go
new file mode 100644
index 0000000..7097642
--- /dev/null
+++ b/server/router/profileroute/controller.go
@@ -0,0 +1,103 @@
+package profileroute
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain"
+ "bitbucket.org/nemt/nemt-portal-api/infra/cache"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ }
+ })
+
+ return instance
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+
+ cache := cache.Instance(c.cfg)
+ cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
+ resp := []viewmodel.Profile{}
+ err := cache.GetStruct(cacheKey, &resp)
+ if err != nil {
+ if err != domain.ErrCacheMiss {
+ ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
+ }
+ resp, err = c.svc.Profile.GetVisibles(true)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ cache.SetStruct(cacheKey, resp)
+ }
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleKey(ctx echo.Context) error {
+
+ key, err := routeutils.GetAndValidateStringParam(ctx, "key", "Key is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ cache := cache.Instance(c.cfg)
+ cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
+ resp := viewmodel.Profile{}
+
+ err = cache.GetStruct(cacheKey, &resp)
+ if err != nil {
+ if err != domain.ErrCacheMiss {
+ ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
+ }
+ resp, err = c.svc.Profile.GetByKey(key)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ cache.SetStruct(cacheKey, resp)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleOrg(ctx echo.Context) error {
+ orgType, err := routeutils.GetAndValidateStringParam(ctx, "org_key", "Org is mandatory")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ cache := cache.Instance(c.cfg)
+ cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
+ resp := []viewmodel.Profile{}
+ err = cache.GetStruct(cacheKey, &resp)
+ if err != nil {
+ if err != domain.ErrCacheMiss {
+ ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
+ }
+ resp, err = c.svc.Profile.GetByOrganizationType(orgType)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ cache.SetStruct(cacheKey, resp)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
diff --git a/server/router/profileroute/router.go b/server/router/profileroute/router.go
new file mode 100644
index 0000000..9c0167e
--- /dev/null
+++ b/server/router/profileroute/router.go
@@ -0,0 +1,21 @@
+package profileroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+ keyRoute = "/:key"
+ orgRoute = "/org/:org_key"
+)
+
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(cfg, svc)
+
+ r.GET(rootRoute, ctrl.handle)
+ r.GET(keyRoute, ctrl.handleKey)
+ r.GET(orgRoute, ctrl.handleOrg)
+}
diff --git a/server/router/providerroute/controller.go b/server/router/providerroute/controller.go
new file mode 100644
index 0000000..360801c
--- /dev/null
+++ b/server/router/providerroute/controller.go
@@ -0,0 +1,178 @@
+package providerroute
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/third/npd"
+ "bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ npd *npd.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ npd: npd.New(cfg),
+ }
+ })
+ return instance
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ var providers []npdmodel.ProviderResponse
+
+ if err := ctx.Bind(&providers); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ authUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ entities, err := c.svc.Provider.Save(providers, authUser)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, entities)
+}
+
+func (c *controller) handleParticipating(ctx echo.Context) error {
+ query := ctx.QueryParam("query")
+ var lat float64
+ var long float64
+ var distance int64
+ distance = 10
+ planCode := ""
+ productID := ""
+ mukID := ""
+ providerID := ""
+ sort := "distance"
+
+ lat, err := routeutils.GetAndValidateFloatQueryParam(ctx, "lat", "latitude is mandatory")
+ if err != nil {
+ lat = 0
+ }
+
+ long, err = routeutils.GetAndValidateFloatQueryParam(ctx, "long", "longitude is mandatory")
+ if err != nil {
+ long = 0
+ }
+
+ planCode, _ = routeutils.GetAndValidateStringQueryParam(ctx, "plan_code", "Plan Code is mandatory")
+ productID, _ = routeutils.GetAndValidateStringQueryParam(ctx, "product_id", "Product ID is mandatory")
+
+ providerID, _ = routeutils.GetAndValidateStringQueryParam(ctx, "provider_id", "Provider ID is mandatory")
+ distance, err = routeutils.GetAndValidateIntQueryParam(ctx, "distance", "distance is mandatory")
+ if err != nil {
+ distance = 1000000
+ }
+
+ sort, err = routeutils.GetAndValidateStringQueryParam(ctx, "sort", "sort is mandatory")
+ if err != nil || (sort != "distance" && sort != "name") {
+ sort = "distance"
+ }
+
+ mukID, _ = routeutils.GetAndValidateStringQueryParam(ctx, "muk_id", "Muk ID is mandatory")
+
+ authUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ // if (lat != 0 && long == 0) || (lat == 0 && long != 0) {
+ // return routeutils.ResponseAPIFieldValidationError(ctx, "coordinates", "Invalid coordinates")
+ // } else {
+ // lat = 41.886406
+ // long = -87.624225
+ // }
+
+ lat = 40.442875
+ long = -80.003112
+
+ if len(mukID) > 0 {
+ query = ""
+ providerID = ""
+ }
+
+ providers, err := c.svc.Provider.Get(query, lat, long, distance, planCode, productID, mukID, providerID, sort, authUser)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, providers)
+}
+
+func (c *controller) handleList(ctx echo.Context) error {
+ name := ctx.QueryParam("name")
+ searchBy := ctx.QueryParam("searchBy")
+
+ // lat, err := routeutils.GetAndValidateFloatQueryParam(ctx, "lat", "latitude is mandatory")
+ // if err != nil {
+ // return err
+ // }
+
+ // long, err := routeutils.GetAndValidateFloatQueryParam(ctx, "long", "longitude is mandatory")
+ // if err != nil {
+ // return err
+ // }
+
+ distance, err := routeutils.GetAndValidateIntQueryParam(ctx, "distance", "distance is mandatory")
+ if err != nil {
+ distance = 10
+ }
+
+ limit, err := routeutils.GetAndValidateIntQueryParam(ctx, "limit", "limit is mandatory")
+ if err != nil {
+ limit = 50
+ }
+
+ sortBy, err := routeutils.GetAndValidateStringQueryParam(ctx, "sortby", "limit is mandatory")
+ if err != nil || (sortBy != "distance" && sortBy != "name") {
+ sortBy = "distance"
+ }
+
+ providerParams := npdmodel.ProviderSearchParams{
+ Name: name,
+ SearchBy: searchBy,
+ Latitude: 40.442875,
+ Longitude: -80.003112,
+ Distance: distance,
+ Limit: limit,
+ Offset: 0,
+ SortBy: sortBy,
+ FacetAcceptNewPatients: "Y",
+ FacetExtendedOfficeHours: "Y",
+ FacetGender: "Y",
+ FacetHospitalAffiliations: "Y",
+ FacetLanguage: "Y",
+ FacetOfficeLanguages: "Y",
+ FacetProviderAffiliations: "Y",
+ FacetProviderEntityName: "Y",
+ FacetSummaryScore: "Y",
+ }
+
+ providers, err := c.npd.Provider.GetProviders(providerParams)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, providers)
+}
diff --git a/server/router/providerroute/router.go b/server/router/providerroute/router.go
new file mode 100644
index 0000000..dfb5e69
--- /dev/null
+++ b/server/router/providerroute/router.go
@@ -0,0 +1,20 @@
+package providerroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+ participatingroute = "/participating"
+)
+
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(cfg, svc)
+
+ r.GET(rootRoute, ctrl.handleList)
+ r.GET(participatingroute, ctrl.handleParticipating)
+ r.POST(rootRoute, ctrl.handle)
+}
diff --git a/server/router/router.go b/server/router/router.go
new file mode 100644
index 0000000..e09067e
--- /dev/null
+++ b/server/router/router.go
@@ -0,0 +1,50 @@
+package router
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/authenticateroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/docsroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/eligibilityroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/externalroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/healthroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/lyfthookroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/notificationroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/organizationroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/placesroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/profileroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/providerroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/tncroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/twilioroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/usersroute"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/visitroute"
+ "github.com/labstack/echo"
+)
+
+// Register registers the API routes
+func Register(e *echo.Echo, cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) {
+ healthroute.Register(e.Group("/health"))
+ prefixGroup := e.Group(cfg.HTTP.Prefix)
+
+ if cfg.App.Debug {
+ docsroute.Register(prefixGroup.Group("/docs"), cfg)
+ }
+
+ notificationroute.Register(prefixGroup.Group("/notification"), cfg, svc, tnc, notification)
+ twilioroute.Register(prefixGroup.Group("/twilio"), cfg, svc, tnc, notification)
+ lyfthookroute.Register(prefixGroup.Group("/lyfthook"), cfg, svc, tnc, notification)
+ externalroute.Register(prefixGroup.Group("/ext"), cfg, svc, tnc, notification)
+ authenticateroute.Register(prefixGroup.Group("/authenticate"), cfg, svc)
+
+ appGroup := prefixGroup.Group("/" + cfg.App.Name)
+ usersroute.Register(appGroup.Group("/users"), cfg, svc)
+ eligibilityroute.Register(appGroup.Group("/eligibility"), cfg, svc)
+ tncroute.Register(appGroup.Group("/rides"), cfg, svc, tnc, notification)
+ visitroute.Register(appGroup.Group("/visits"), cfg, svc)
+ providerroute.Register(appGroup.Group("/provider"), cfg, svc)
+ placesroute.Register(appGroup.Group("/places"), cfg, svc)
+ profileroute.Register(appGroup.Group("/profile"), cfg, svc)
+ organizationroute.Register(appGroup.Group("/organization"), cfg, svc)
+}
diff --git a/server/router/routeutils/request.go b/server/router/routeutils/request.go
new file mode 100644
index 0000000..5e2fa64
--- /dev/null
+++ b/server/router/routeutils/request.go
@@ -0,0 +1,130 @@
+package routeutils
+
+import (
+ "strconv"
+
+ "strings"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/labstack/echo"
+)
+
+// GetAndValidateIntParam gets the integer param value and validates it, returning a validation error in case it's invalid
+func GetAndValidateIntParam(c echo.Context, paramName string, errorMessage string) (ID int64, err error) {
+ IDstr := c.Param(paramName)
+
+ if strings.TrimSpace(IDstr) == "" {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ ID, err = strconv.ParseInt(IDstr, 10, 64)
+ if ID == 0 {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ return
+}
+
+// GetAndValidateIntQueryParam gets the integer param value and validates it, returning a validation error in case it's invalid
+func GetAndValidateIntQueryParam(c echo.Context, paramName string, errorMessage string) (ID int64, err error) {
+ IDstr := c.QueryParam(paramName)
+
+ if strings.TrimSpace(IDstr) == "" {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ ID, err = strconv.ParseInt(IDstr, 10, 64)
+ if ID == 0 {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ return
+}
+
+// GetAndValidateFloatParam gets the integer param value and validates it, returning a validation error in case it's invalid
+func GetAndValidateFloatQueryParam(c echo.Context, paramName string, errorMessage string) (ID float64, err error) {
+ IDstr := c.QueryParam(paramName)
+
+ if strings.TrimSpace(IDstr) == "" {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ ID, err = strconv.ParseFloat(IDstr, 64)
+ if ID == 0 {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ return
+}
+
+// GetAndValidateStringQueryParam gets the integer param value and validates it, returning a validation error in case it's invalid
+func GetAndValidateStringQueryParam(c echo.Context, paramName string, errorMessage string) (ID string, err error) {
+ ID = c.QueryParam(paramName)
+
+ if strings.TrimSpace(ID) == "" {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ return
+}
+
+// GetAndValidateStringParam gets the string param value and validates it, returning a validation error in case it's invalid
+func GetAndValidateStringParam(c echo.Context, paramName string, errorMessage string) (ID string, err error) {
+ ID = c.Param(paramName)
+
+ if strings.TrimSpace(ID) == "" {
+ err = errors.NewValidationError(paramName, errorMessage)
+ }
+
+ return
+}
+
+// GetPagingParams gets the standard paging params from the URL, returning a validation error in case it's invalid
+func GetPagingParams(c echo.Context) (page int64, quantity int64) {
+ pg := c.QueryParam("page")
+ ipp := c.QueryParam("quantity")
+
+ page, _ = strconv.ParseInt(pg, 10, 64)
+ quantity, _ = strconv.ParseInt(ipp, 10, 64)
+
+ if page < 1 {
+ page = 1
+ }
+
+ if quantity < 1 || quantity > 1000 {
+ quantity = 10
+ }
+
+ return
+}
+
+// GetMultipleQueryParam returns a list of values for multiple query params
+func GetMultipleQueryParam(c echo.Context, paramName string) (retVal []string) {
+ retVal = make([]string, 0)
+
+ for k, param := range map[string][]string(c.QueryParams()) {
+ if k == paramName {
+ for _, value := range param {
+ retVal = append(retVal, value)
+ }
+ break
+ }
+ }
+
+ return retVal
+}
+
+// GetMultipleIntQueryParam returns a list of integer values from multiple query params
+func GetMultipleIntQueryParam(c echo.Context, paramName string) (retVal []int64, err error) {
+ retVal = make([]int64, 0)
+
+ for _, value := range GetMultipleQueryParam(c, paramName) {
+ intValue, err := strconv.ParseInt(value, 10, 64)
+ if err != nil {
+ return retVal, errors.Wrap(err)
+ }
+ retVal = append(retVal, intValue)
+ }
+
+ return retVal, nil
+}
diff --git a/server/router/routeutils/response.go b/server/router/routeutils/response.go
new file mode 100644
index 0000000..0d95b6f
--- /dev/null
+++ b/server/router/routeutils/response.go
@@ -0,0 +1,204 @@
+package routeutils
+
+import (
+ "database/sql"
+ "fmt"
+ "net"
+ "net/http"
+ "os/exec"
+ "reflect"
+ "strings"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/aws/aws-sdk-go/aws/awserr"
+ "github.com/go-sql-driver/mysql"
+ "github.com/labstack/echo"
+)
+
+// resultWrapper has fields for standard message responses
+type resultWrapper struct {
+ Error bool `json:"error,omitempty"`
+ Message string `json:"message,omitempty"`
+ Redirect bool `json:"redirect,omitempty"`
+ Data interface{} `json:"data,omitempty"`
+}
+
+// ResponseNoContent returns a standard API success with no content response
+func ResponseNoContent(c echo.Context, data interface{}) error {
+ return c.NoContent(http.StatusNoContent)
+}
+
+// ResponseAPIOK returns a standard API success response
+func ResponseAPIOK(c echo.Context, data interface{}) error {
+ return c.JSON(http.StatusOK, data)
+}
+
+// ResponseAPIError returns a standard API error to the response
+func ResponseAPIError(c echo.Context, status int, message string, redirect bool) error {
+ returnValue := resultWrapper{
+ Error: true,
+ Message: message,
+ Redirect: redirect,
+ }
+
+ return c.JSON(status, returnValue)
+}
+
+// ResponseAPIAuthError returns a standard API auth error to the response
+func ResponseAPIAuthError(c echo.Context, message string, redirect bool) error {
+ return ResponseAPIError(c, http.StatusUnauthorized, message, redirect)
+}
+
+// ResponseAPIServiceError returns a standard API service unavailable error to the response
+func ResponseAPIServiceError(c echo.Context, message string) error {
+ return ResponseAPIError(c, http.StatusServiceUnavailable, message, false)
+}
+
+// ResponseAPIValidationError returns a standard API validation error to the response
+func ResponseAPIValidationError(c echo.Context, message string) error {
+ return ResponseAPIError(c, http.StatusUnprocessableEntity, message, false)
+}
+
+// ResponseAPIFieldValidationError returns a standard API field validation error to the response
+func ResponseAPIFieldValidationError(c echo.Context, field string, message string) error {
+ err := errors.NewValidationError(field, message)
+ return HandleAPIError(c, err)
+}
+
+// ResponseAPINotFoundError returns a standard API not found error to the response
+func ResponseAPINotFoundError(c echo.Context) error {
+ return ResponseAPIError(c, http.StatusNotFound, "Not Found", false)
+}
+
+func ignoreDefaultWrappedErrors(c echo.Context, errorToHandle *errors.WrappedError, handler func(echo.Context, error) error) error {
+ err := errorToHandle.GetOriginalError()
+
+ if err != nil {
+ switch e := (*err).(type) {
+ case *errors.ValidationError:
+ case *errors.NotAuthorizedError:
+ case *errors.HTTPError:
+ case awserr.Error:
+ default:
+ if e != sql.ErrNoRows {
+ c.Logger().Errorf("%s", e.Error())
+ }
+ }
+
+ return handler(c, *err)
+ }
+
+ return nil
+}
+
+// HandleAPIError applies the default error handling to the response
+func HandleAPIError(c echo.Context, errorToHandle error) (err error) {
+ statusCode := http.StatusServiceUnavailable
+ errorMessage := "Service Unavailable"
+
+ if errorToHandle != nil {
+ logger := c.Logger()
+ errorString := errorToHandle.Error()
+
+ switch e := errorToHandle.(type) {
+ case *errors.WrappedError:
+ return ignoreDefaultWrappedErrors(c, e, HandleAPIError)
+
+ case *errors.ApplicationError:
+ logger.Errorf("Application Error: %s - %v", e.Path, e.Message)
+
+ case *errors.ValidationError:
+ return ResponseAPIValidationError(c, errorString)
+
+ case *errors.NotAuthorizedError:
+ statusCode = http.StatusUnauthorized
+ errorMessage = errorString
+
+ case *errors.HTTPError:
+ statusCode = e.Status
+ errorMessage = e.Message
+
+ case *mysql.MySQLError:
+ logger.Errorf("MySQL Error: %v - %v", e.Number, e.Message)
+ errorMessage = "Service temporarily unavailable"
+
+ case net.Error:
+ logger.Errorf("Network/Connection error: %v", e.Error())
+ errorMessage = "Service temporarily unavailable"
+
+ case *echo.HTTPError:
+ statusCode = e.Code
+ errorMessage = fmt.Sprint(e.Message)
+
+ case *exec.ExitError:
+ logger.Errorf("Exec Error: %s - %v", e.ProcessState, e.Error())
+
+ default:
+ if e == sql.ErrNoRows {
+ logger.Debugf("SQL Error: %v", e.Error())
+ return ResponseAPINotFoundError(c)
+ } else if e == sql.ErrTxDone || strings.HasPrefix(errorString, "sql: ") {
+ logger.Errorf("SQL Error: %v", e.Error())
+ return ResponseAPIServiceError(c, "Service temporarily unavailable")
+ }
+
+ logger.Errorf("%v: %v", reflect.TypeOf(e), e.Error())
+ }
+ }
+
+ return ResponseAPIError(c, statusCode, errorMessage, false)
+}
+
+// HandleHTMLError applies the default error handling to the response
+func HandleHTMLError(c echo.Context, errorToHandle error) error {
+ statusCode := http.StatusServiceUnavailable
+ errorMessage := "Service Unavailable"
+
+ if errorToHandle != nil {
+ logger := c.Logger()
+ errorString := errorToHandle.Error()
+
+ switch e := errorToHandle.(type) {
+ case *errors.WrappedError:
+ return ignoreDefaultWrappedErrors(c, e, HandleHTMLError)
+
+ case *errors.ApplicationError:
+ logger.Errorf("Application Error: %s - %v", e.Path, e.Message)
+
+ case *errors.ValidationError:
+ return ResponseAPIValidationError(c, errorString)
+
+ case *errors.NotAuthorizedError:
+ return ResponseAPIError(c, http.StatusUnauthorized, errorString, false)
+
+ case *errors.HTTPError:
+ errorMessage = e.Message
+
+ case *mysql.MySQLError:
+ logger.Errorf("MySQL Error: %v - %v", e.Number, e.Message)
+ errorMessage = "Service temporarily unavailable"
+
+ case net.Error:
+ logger.Errorf("Network/Connection error: %v", e.Error())
+ errorMessage = "Service temporarily unavailable"
+
+ case *echo.HTTPError:
+ logger.Errorf("%v: %v - %v", reflect.TypeOf(e), e.Code, e.Message)
+ statusCode = e.Code
+
+ default:
+ if e == sql.ErrNoRows {
+ logger.Debugf("SQL Error: %v", e.Error())
+ statusCode = http.StatusNotFound
+ errorMessage = "Not Found"
+ } else if e == sql.ErrTxDone || strings.HasPrefix(errorString, "sql: ") {
+ logger.Errorf("SQL Error: %v", e.Error())
+ errorMessage = "Service temporarily unavailable"
+ } else {
+ logger.Errorf("%v: %v", reflect.TypeOf(e), e.Error())
+ }
+ }
+ }
+
+ return c.HTML(statusCode, errorMessage)
+}
diff --git a/server/router/tncroute/controller.go b/server/router/tncroute/controller.go
new file mode 100644
index 0000000..6e11d24
--- /dev/null
+++ b/server/router/tncroute/controller.go
@@ -0,0 +1,872 @@
+package tncroute
+
+import (
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+ uuid "github.com/satori/go.uuid"
+ "google.golang.org/api/googleapi/transport"
+ urlshortener "google.golang.org/api/urlshortener/v1"
+
+ "github.com/gorilla/websocket"
+)
+
+var (
+ instance *controller
+ once sync.Once
+ upgrader = websocket.Upgrader{}
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ tnc *tncservice.Service
+ notification *notificationservice.Service
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ tnc: tnc,
+ notification: notification,
+ }
+ })
+ return instance
+}
+
+func (c *controller) handleSocket(ctx echo.Context) error {
+ ws, err := upgrader.Upgrade(ctx.Response(), ctx.Request(), nil)
+ if err != nil {
+ return err
+ }
+ defer ws.Close()
+
+ for {
+ // Write
+ err := ws.WriteMessage(websocket.TextMessage, []byte("Hello, Client!"))
+ if err != nil {
+ ctx.Logger().Error(err)
+ }
+
+ // Read
+ _, msg, err := ws.ReadMessage()
+ if err != nil {
+ ctx.Logger().Error(err)
+ }
+ fmt.Printf("%s\n", msg)
+ }
+}
+
+func (c *controller) handleMessage(ctx echo.Context) error {
+ rideID := ctx.Param("ride_uuid")
+ if rideID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "rideID param is mandatory")
+ }
+
+ message := make(map[string]string)
+ err := ctx.Bind(&message)
+ if err != nil || message["message"] == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "message body param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ notifications := make([]viewmodel.Notification, 0)
+ notifications = append(notifications, c.svc.Notification.GetNotification(ride, "sms", "A message to member", message["message"], false, "message"))
+ notifications = append(notifications, c.svc.Notification.GetNotification(ride, "app", "A message to member", message["message"], false, "message"))
+
+ notifications, err = c.svc.Notification.SendNotifications(notifications)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, notifications)
+}
+
+func (c *controller) getURLShortened(ride viewmodel.Ride) (string, error) {
+ const (
+ url = "https://portal.bcbsinstitute.com/#/ride/%s/%s"
+ )
+
+ svc, err := urlshortener.New(&http.Client{
+ Transport: &transport.APIKey{Key: c.cfg.GoogleShortener.APIKey},
+ })
+ if err != nil {
+ return "", err
+ }
+
+ userURL := fmt.Sprintf(url, ride.UUID, ride.User.ID)
+ shortURL, err := svc.Url.Insert(&urlshortener.Url{
+ Kind: "urlshortener#url", // Not really needed
+ LongUrl: userURL,
+ }).Do()
+ if err != nil {
+ return "", err
+ }
+
+ return shortURL.Id, nil
+}
+
+func (c *controller) handleShare(ctx echo.Context) error {
+ const (
+ message = "%s shared a link with you for an upcoming ride: %s"
+ )
+
+ rideID := ctx.Param("ride_uuid")
+ if rideID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "rideID param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ url, err := c.getURLShortened(ride)
+ if err != nil {
+ fmt.Println("Error to short url: ", err)
+ }
+
+ notifications := make([]viewmodel.Notification, 0)
+ notifications = append(notifications, c.svc.Notification.GetNotification(ride, "sms", "A ride was shared with you", fmt.Sprintf(message, ride.CreatedUser.Name, url), false, "message"))
+ notifications = append(notifications, c.svc.Notification.GetNotification(ride, "email", "A ride was shared with you", fmt.Sprintf(message, ride.CreatedUser.Name, url), false, "message"))
+ notifications = append(notifications, c.svc.Notification.GetNotification(ride, "app", "A ride was shared with you", fmt.Sprintf(message, ride.CreatedUser.Name, url), false, "message"))
+
+ notifications, err = c.svc.Notification.SendNotifications(notifications)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, notifications)
+}
+
+func (c *controller) handleMessageDriver(ctx echo.Context) error {
+ rideID := ctx.Param("ride_uuid")
+ if rideID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "rideID param is mandatory")
+ }
+
+ message := make(map[string]string)
+ err := ctx.Bind(&message)
+ if err != nil || message["message"] == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "message body param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ notifications := make([]viewmodel.Notification, 0)
+ if ride.Status.Key == "accepted" || ride.Status.Key == "arrived" || ride.Status.Key == "pickedUp" {
+ notifications = append(notifications, c.getDriverNotification(ride, "sms", "A message to driver", message["message"], ride.Driver.PhoneNumber, *ride.CreatedUser.PhoneNumber))
+ notifications, err = c.svc.Notification.SendNotifications(notifications)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ }
+ return routeutils.ResponseAPIOK(ctx, notifications)
+}
+
+func (c *controller) handleList(ctx echo.Context) error {
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ entity, err := c.svc.Rides.GetAll(user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ctx.Response().Header().Set("Content-Type", "application/json")
+ return routeutils.ResponseAPIOK(ctx, entity)
+}
+
+func (c *controller) handle(ctx echo.Context) error {
+ var requestRide viewmodel.RideRequest
+ err := ctx.Bind(&requestRide)
+ if err != nil {
+ fmt.Println(err)
+ return routeutils.ResponseAPIValidationError(ctx, "invalid parameters")
+ }
+
+ user, err := c.svc.Users.GetByUUID(requestRide.UserUUID, "US")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ if user.ID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "User not found")
+ }
+
+ createdUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ name := user.Name
+ names := strings.Split(name, " ")
+ requestRide.Passenger.FirstName = names[0]
+ requestRide.Passenger.LastName = " "
+ requestRide.Passenger.PhoneNumber = *user.PhoneNumber
+
+ var resp viewmodel.RideRequest
+ if requestRide.TripType.Key != "from_visit_call" {
+ if requestRide.TripType.Key == "from_visit" {
+ newOrigin := requestRide.Origin
+ requestRide.Origin = requestRide.Destination
+ requestRide.Destination = newOrigin
+ }
+
+ if c.cfg.LyftProd.UserUUID != createdUser.ID {
+ resp, err = c.tnc.Lyft.RequestRide(requestRide)
+ } else {
+ fmt.Println("In Production")
+ resp, err = c.tnc.LyftProd.RequestRide(requestRide)
+ }
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if requestRide.TripType.Key == "from_visit" {
+ newOrigin := resp.Origin
+ resp.Origin = resp.Destination
+ resp.Destination = newOrigin
+ }
+
+ resp.RideID = strings.Replace(resp.RideID, "s_", "", -1)
+ } else {
+ resp = requestRide
+
+ UUID, _ := uuid.NewV4()
+ resp.RideID = UUID.String()
+ }
+
+ if resp.Status == "scheduled" || requestRide.TripType.Key == "from_visit_call" {
+ if requestRide.PickupTime == nil {
+ currentDate := time.Now()
+ requestRide.PickupTime = ¤tDate
+ }
+ requestMS := (requestRide.PickupTime.UnixNano() / int64(time.Millisecond))
+ generateDate := time.Now()
+ generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
+ resp.RequestAt = requestRide.PickupTime
+ resp.RequestAtMS = &requestMS
+ resp.GeneratedAt = &generateDate
+ resp.GeneratedAtMS = &generateMS
+ }
+
+ resp.Passenger.FirstName = names[0]
+ resp.Passenger.LastName = names[len(names)-1]
+ resp.Passenger.PhoneNumber = *user.PhoneNumber
+
+ if resp.Passenger.ImageURL == nil {
+ imageURL := " "
+ resp.Passenger.ImageURL = &imageURL
+ }
+
+ resp.UserUUID = requestRide.UserUUID
+
+ if requestRide.TripType.Key == "from_visit" {
+ resp.Origin.Name = requestRide.Destination.Name
+ resp.Origin.ID = requestRide.Destination.ID
+ resp.Destination.Name = requestRide.Origin.Name
+ resp.Destination.ID = requestRide.Origin.ID
+ } else {
+ resp.Origin.Name = requestRide.Origin.Name
+ resp.Origin.ID = requestRide.Origin.ID
+ resp.Destination.Name = requestRide.Destination.Name
+ resp.Destination.ID = requestRide.Destination.ID
+ }
+
+ resp.Distance = requestRide.Distance
+ resp.Duration = requestRide.Duration
+ resp.ETA = requestRide.ETA
+ resp.PickupTime = requestRide.PickupTime
+ resp.VisitDate = requestRide.VisitDate
+ resp.VisitTime = requestRide.VisitTime
+ resp.VisitExternalID = requestRide.VisitExternalID
+ resp.CreateUserUUID = createdUser.ID
+ resp.Visit.TripType = requestRide.TripType
+
+ if resp.TripType.Key == "from_visit_call" {
+ resp.Status = "willCall"
+ resp.Passenger.UserID = &resp.UserUUID
+ }
+
+ resp.TripType.Key = requestRide.TripType.Key
+ if requestRide.TripType.Key == "roundtrip" || requestRide.TripType.Key == "roundtrip_call" {
+ resp.TripType.Key = "to_visit"
+ } else if requestRide.TripType.Key == "from_visit_call" {
+ resp.TripType.Key = "from_visit_call"
+ }
+
+ entity, err := c.svc.Rides.Save(resp)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ go func() {
+ err = c.svc.Notification.SendNotification(resp.Status, entity, resp)
+ if err != nil {
+ fmt.Println("Error to notify user: ", err.Error())
+ }
+ }()
+
+ if requestRide.TripType.Key == "roundtrip" || requestRide.TripType.Key == "roundtrip_call" {
+ newRide := requestRide
+
+ if requestRide.TripType.Key == "roundtrip" {
+ destination := newRide.Origin
+ newRide.Origin = newRide.Destination
+ newRide.Destination = destination
+ if requestRide.ReturnTime != nil {
+ newRide.PickupTime = requestRide.ReturnTime
+ }
+
+ scheduledRide := make(map[string]interface{})
+ scheduledRide["timestamp_ms"] = requestRide.PickupTime.Unix()
+ newRide.ScheduledPickupRange = scheduledRide
+
+ newRide.Passenger.FirstName = names[0]
+ newRide.Passenger.LastName = " "
+ newRide.Passenger.PhoneNumber = *user.PhoneNumber
+
+ if c.cfg.LyftProd.UserUUID != createdUser.ID {
+ newRide, err = c.tnc.Lyft.RequestRide(newRide)
+ } else {
+ fmt.Println("In Production")
+ newRide, err = c.tnc.LyftProd.RequestRide(newRide)
+ }
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ destination = newRide.Origin
+ newRide.Origin = newRide.Destination
+ newRide.Destination = destination
+
+ if newRide.Error != "" {
+ fmt.Println("Error to schedule a ride on lyft: ", newRide.Error, newRide.ErrorDescription)
+ } else {
+ fmt.Println("Ride Scheduled: ", newRide.Status)
+ }
+
+ newRide.TripType.Key = "from_visit"
+ } else {
+ newRide.TripType.Key = "from_visit_call"
+ newRide.Status = "willCall"
+ newRide.RideID = entity.UUID
+ }
+
+ newRide.Visit = entity.Visit
+ newRide.PickupTime = requestRide.ReturnTime
+
+ requestMS := (newRide.PickupTime.UnixNano() / int64(time.Millisecond))
+ generateDate := time.Now()
+ generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
+ newRide.RequestAt = newRide.PickupTime
+ newRide.RequestAtMS = &requestMS
+ newRide.GeneratedAt = &generateDate
+ newRide.GeneratedAtMS = &generateMS
+
+ newRide.Passenger.FirstName = names[0]
+ newRide.Passenger.LastName = names[len(names)-1]
+ newRide.Passenger.PhoneNumber = *user.PhoneNumber
+ newRide.Passenger.UserID = &requestRide.UserUUID
+
+ if newRide.Passenger.ImageURL == nil {
+ imageURL := " "
+ newRide.Passenger.ImageURL = &imageURL
+ }
+
+ newRide.UserUUID = requestRide.UserUUID
+ newRide.Origin.Name = requestRide.Destination.Name
+ newRide.Origin.ID = requestRide.Destination.ID
+ newRide.Destination.Name = requestRide.Origin.Name
+ newRide.Destination.ID = requestRide.Origin.ID
+ newRide.Distance = requestRide.Distance
+ newRide.Duration = requestRide.Duration
+ newRide.ETA = requestRide.ETA
+ newRide.VisitDate = requestRide.VisitDate
+ newRide.VisitTime = requestRide.VisitTime
+ newRide.VisitExternalID = requestRide.VisitExternalID
+ newRide.CreateUserUUID = createdUser.ID
+
+ roudtripRide, err := c.svc.Rides.Save(newRide)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ go func() {
+ err = c.svc.Notification.SendNotification(newRide.Status, roudtripRide, newRide)
+ if err != nil {
+ fmt.Println("Error to notify user: ", err.Error())
+ }
+ }()
+ }
+
+ ctx.Response().Header().Set("Content-Type", "application/json")
+ return routeutils.ResponseAPIOK(ctx, entity)
+}
+
+func (c *controller) getDriverNotification(ride viewmodel.Ride, notificationType string, subject string, message string, to string, from string) viewmodel.Notification {
+ retVal := viewmodel.Notification{
+ Type: notificationType,
+ Message: message,
+ Subject: subject,
+ Ride: ride,
+ User: ride.User,
+ CreatedUser: ride.CreatedUser,
+ To: to,
+ From: from,
+ }
+
+ return retVal
+}
+
+func (c *controller) handleRawLyft(ctx echo.Context) error {
+ rideUUID := ctx.Param("ride_uuid")
+ if rideUUID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideUUID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ var lyftRide viewmodel.RideRequest
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ }
+ if err != nil {
+ fmt.Println("Error getting lyft details: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, lyftRide)
+}
+
+func (c *controller) handleRideETA(ctx echo.Context) error {
+ rideUUID := ctx.Param("ride_uuid")
+ if rideUUID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideUUID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
+ var lyftRide viewmodel.RideRequest
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ }
+ if err != nil {
+ fmt.Println("Error getting lyft details: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride.Route.Location = ride.Route.Origin
+ ride.Route.Location.Address = ""
+ ride.Route.Location.Name = ""
+
+ switch lyftRide.Status {
+ case "scheduled":
+ ride.Route.ETA = ride.PickupTime.UnixNano() / int64(time.Second)
+ case "accepted":
+ if lyftRide.Origin.ETASeconds != nil {
+ ride.Route.ETA = *lyftRide.Origin.ETASeconds
+ } else {
+ ride.Route.ETA = 0
+ if c.cfg.App.Debug {
+ ride.Route.ETA = 350
+ }
+ }
+ case "arrived", "pickedUp":
+ if lyftRide.Destination.ETASeconds != nil {
+ ride.Route.ETA = *lyftRide.Destination.ETASeconds
+ } else {
+ ride.Route.ETA = 0
+ if c.cfg.App.Debug {
+ ride.Route.ETA = 350
+ }
+ }
+ }
+
+ if lyftRide.Location.Latitude != 0 && lyftRide.Location.Longitude != 0 {
+ ride.Route.Location = lyftRide.Location
+ }
+ }
+
+ return routeutils.ResponseAPIOK(ctx, ride)
+}
+
+func (c *controller) handleCancel(ctx echo.Context) error {
+ var requestRide viewmodel.RideRequest
+ rideUUID := ctx.Param("ride_uuid")
+ if rideUUID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideUUID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ requestRide.RideID = ride.InternalID
+ if ride.Status.Key == "scheduled" && !strings.Contains(ride.InternalID, "s_") {
+ requestRide.RideID = "s_" + ride.InternalID
+ }
+
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ err = c.tnc.Lyft.CancelRide(requestRide)
+ if err != nil && err.Error() == "ride_not_found" {
+ err = nil
+ }
+ } else {
+ fmt.Println("In Production")
+ err = c.tnc.LyftProd.CancelRide(requestRide)
+ }
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ err = c.svc.Rides.UpdateStatus(rideUUID, "canceled")
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ // ride.Status.Key = "canceled"
+
+ // go func() {
+ // err = c.svc.Notification.SendNotification(ride.Status.Key, ride, viewmodel.RideRequest{})
+ // if err != nil {
+ // fmt.Println("Error: ", err.Error())
+ // }
+ // }()
+
+ ctx.Response().Header().Set("Content-Type", "application/json")
+ return routeutils.ResponseNoContent(ctx, nil)
+}
+
+func (c *controller) handleETA(ctx echo.Context) error {
+ sLat := ctx.Param("lat")
+ if sLat == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory")
+ }
+
+ sLog := ctx.Param("log")
+ if sLog == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory")
+ }
+
+ sDestLat := ctx.Param("destlat")
+ if sLat == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory")
+ }
+
+ sDestLog := ctx.Param("destlong")
+ if sLog == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory")
+ }
+
+ lat, err := strconv.ParseFloat(strings.TrimSpace(sLat), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "lat invalid")
+ }
+
+ log, err := strconv.ParseFloat(strings.TrimSpace(sLog), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "log invalid")
+ }
+
+ destlat, err := strconv.ParseFloat(strings.TrimSpace(sDestLat), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "destination lat invalid")
+ }
+
+ destlog, err := strconv.ParseFloat(strings.TrimSpace(sDestLog), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "destination log invalid")
+ }
+
+ params := map[string]interface{}{}
+ params["endLat"] = destlat
+ params["endLng"] = destlog
+ params["rideType"] = "lyft"
+
+ resp, err := c.tnc.Lyft.GetCost(lat, log, params)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleRide(ctx echo.Context) error {
+ rideUUID := ctx.Param("ride_uuid")
+ if rideUUID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideUUID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
+ var lyftRide viewmodel.RideRequest
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ }
+ if err != nil {
+ fmt.Println("Error getting lyft details: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride.Route.Location = ride.Route.Origin
+ ride.Route.Location.Address = ""
+ ride.Route.Location.Name = ""
+
+ switch lyftRide.Status {
+ case "scheduled":
+ ride.Route.ETA = ride.PickupTime.UnixNano() / int64(time.Second)
+ case "accepted":
+ if lyftRide.Origin.ETASeconds != nil {
+ ride.Route.ETA = *lyftRide.Origin.ETASeconds
+ } else {
+ ride.Route.ETA = 0
+ if c.cfg.App.Debug {
+ ride.Route.ETA = 350
+ }
+ }
+ case "arrived":
+ if lyftRide.Destination.ETASeconds != nil {
+ ride.Route.ETA = *lyftRide.Destination.ETASeconds
+ } else {
+ ride.Route.ETA = 0
+ }
+ case "pickedUp":
+ if lyftRide.Destination.ETASeconds != nil {
+ ride.Route.ETA = *lyftRide.Destination.ETASeconds
+ } else {
+ ride.Route.ETA = 0
+ if c.cfg.App.Debug {
+ ride.Route.ETA = 350
+ }
+ }
+ }
+
+ if lyftRide.Location.Latitude != 0 && lyftRide.Location.Longitude != 0 {
+ ride.Route.Location = lyftRide.Location
+ }
+ }
+
+ return routeutils.ResponseAPIOK(ctx, ride)
+}
+
+func (c *controller) handleDrivers(ctx echo.Context) error {
+ sLat := ctx.Param("lat")
+ if sLat == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory")
+ }
+
+ sLog := ctx.Param("log")
+ if sLog == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory")
+ }
+
+ lat, err := strconv.ParseFloat(strings.TrimSpace(sLat), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "lat invalid")
+ }
+
+ log, err := strconv.ParseFloat(strings.TrimSpace(sLog), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "log invalid")
+ }
+
+ resp, err := c.tnc.Lyft.GetDrivers(lat, log)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleTypes(ctx echo.Context) error {
+ sLat := ctx.Param("lat")
+ if sLat == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory")
+ }
+
+ sLog := ctx.Param("log")
+ if sLog == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory")
+ }
+
+ lat, err := strconv.ParseFloat(strings.TrimSpace(sLat), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "lat invalid")
+ }
+
+ log, err := strconv.ParseFloat(strings.TrimSpace(sLog), 64)
+ if err != nil {
+ return routeutils.ResponseAPIValidationError(ctx, "log invalid")
+ }
+
+ resp, err := c.tnc.Lyft.GetTypes(lat, log, nil)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleReady(ctx echo.Context) error {
+ var rideUUID = ctx.Param("ride_uuid")
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ ride, err := c.svc.Rides.GetByUUID(rideUUID, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ var nextRide viewmodel.Ride
+ if ride.TripType.Key == "from_visit_call" && ride.Status.Key == "willCall" {
+ nextRide = ride
+ } else if ride.Visit.TripType.Key == "roundtrip_call" && ride.TripType.Key == "to_visit" {
+ roundTripRide, err := c.svc.Rides.GetByVisitUUIDAndTripType(ride.Visit.UUID, "from_visit_call", user)
+ if err != nil {
+ fmt.Println("Error to get next ride: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ nextRide = roundTripRide
+ } else {
+ fmt.Println("Error on get next ride ")
+ return routeutils.ResponseAPINotFoundError(ctx)
+ }
+
+ var lyftRide viewmodel.RideRequest
+ if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
+ }
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ lyftRide.RideID = ""
+ lyftRide.Destination = ride.Route.Destination
+ lyftRide.Origin = ride.Route.Origin
+
+ name := nextRide.User.Name
+ names := strings.Split(name, " ")
+ lyftRide.Passenger.FirstName = names[0]
+ lyftRide.Passenger.LastName = " "
+ lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
+ lyftRide.RideType = "lyft"
+
+ if c.cfg.LyftProd.UserUUID != nextRide.CreatedUser.ID {
+ lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.RequestRide(lyftRide)
+ }
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ currentTime := time.Now()
+ lyftRide.PickupTime = ¤tTime
+ lyftRide.ReturnTime = ¤tTime
+ nextRide.PickupTime = ¤tTime
+
+ nextRide, err = c.svc.Rides.UpdateNewRide(nextRide, lyftRide, user)
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ go func() {
+ err = c.svc.Notification.SendNotification(lyftRide.Status, nextRide, lyftRide)
+ if err != nil {
+ fmt.Println("Error to notify user: ", err.Error())
+ }
+ }()
+
+ return routeutils.ResponseAPIOK(ctx, nextRide)
+}
diff --git a/server/router/tncroute/router.go b/server/router/tncroute/router.go
new file mode 100644
index 0000000..4a2b873
--- /dev/null
+++ b/server/router/tncroute/router.go
@@ -0,0 +1,52 @@
+package tncroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+ rideRoute = "/:ride_uuid"
+ rawRideRoute = "/:ride_uuid/raw"
+ cancelRoute = "/:ride_uuid/cancel"
+ shareRoute = "/:ride_uuid/share"
+ readyRoute = "/:ride_uuid/ready"
+ etaDetailsRoute = "/:ride_uuid/eta"
+ etaRoute = "/eta/:lat/:log/:destlat/:destlong"
+ ridersRoute = "/drivers/:lat/:log"
+ typesRoute = "/types/:lat/:log"
+ messageRoute = "/:ride_uuid/message"
+ messageDriverRoute = "/:ride_uuid/message/driver"
+ wsRoute = "/ws"
+)
+
+// Register authenticate route
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) {
+
+ ctrl := controllerInstance(cfg, svc, tnc, notification)
+
+ r.GET(rootRoute, ctrl.handleList)
+ r.POST(rootRoute, ctrl.handle)
+ r.GET(rideRoute, ctrl.handleRide)
+
+ r.POST(cancelRoute, ctrl.handleCancel)
+ r.POST(readyRoute, ctrl.handleReady)
+ r.POST(messageRoute, ctrl.handleMessage)
+ r.POST(shareRoute, ctrl.handleShare)
+ r.POST(messageDriverRoute, ctrl.handleMessageDriver)
+
+ r.GET(etaRoute, ctrl.handleETA)
+ r.GET(etaDetailsRoute, ctrl.handleRideETA)
+ r.GET(ridersRoute, ctrl.handleDrivers)
+ r.GET(typesRoute, ctrl.handleTypes)
+ r.GET(wsRoute, ctrl.handleSocket)
+
+ if cfg.App.Debug {
+ r.GET(rawRideRoute, ctrl.handleRawLyft)
+ }
+
+}
diff --git a/server/router/twilioroute/controller.go b/server/router/twilioroute/controller.go
new file mode 100644
index 0000000..3110aca
--- /dev/null
+++ b/server/router/twilioroute/controller.go
@@ -0,0 +1,363 @@
+package twilioroute
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "strings"
+ "sync"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/gorilla/websocket"
+ "github.com/labstack/echo"
+ "github.com/ttacon/libphonenumber"
+)
+
+var (
+ instance *controller
+ once sync.Once
+ upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+ CheckOrigin: func(r *http.Request) bool {
+ return true
+ },
+ }
+)
+
+type controller struct {
+ cfg *config.Config
+ svc *applicationservice.Service
+ tnc *tncservice.Service
+ notification *notificationservice.Service
+ broadcast chan viewmodel.SocketMessage
+ clients map[*websocket.Conn]viewmodel.SocketMessage
+}
+
+func controllerInstance(cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) *controller {
+ once.Do(func() {
+ instance = &controller{
+ cfg: cfg,
+ svc: svc,
+ tnc: tnc,
+ notification: notification,
+ broadcast: make(chan viewmodel.SocketMessage),
+ clients: make(map[*websocket.Conn]viewmodel.SocketMessage),
+ }
+ go instance.handleMessages()
+ })
+ return instance
+}
+
+type Response struct {
+ Message *Message `xml:"Message,omitempty"`
+}
+
+type Message struct {
+ To string `xml:"to,attr"`
+ Body string `xml:"Body,omitempty"`
+}
+
+func (c *controller) getDriverNotification(ride viewmodel.Ride, notificationType string, subject string, message string, to string, from string) viewmodel.Notification {
+ retVal := viewmodel.Notification{
+ Type: notificationType,
+ Message: message,
+ Subject: subject,
+ Ride: ride,
+ User: ride.User,
+ CreatedUser: ride.CreatedUser,
+ To: to,
+ From: from,
+ }
+
+ return retVal
+}
+
+func (c *controller) handleTwilio(ctx echo.Context) error {
+ var twilioResponse viewmodel.TwilioWebhook
+ err := ctx.Bind(&twilioResponse)
+ if err != nil {
+ fmt.Println("Error binding response: ", err.Error())
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ // bResp, _ := json.MarshalIndent(twilioResponse, "", "\t")
+ // fmt.Println("Twilio Request")
+ // fmt.Println(string(bResp))
+
+ var resp Response
+ requestMessage := strings.ToUpper(strings.TrimSpace(twilioResponse.Body))
+ if requestMessage != "CANCEL RIDE" && requestMessage != "YES" && requestMessage != "NO" && !strings.HasPrefix(requestMessage, "DRIVER") && !strings.HasPrefix(requestMessage, "MEMBER") && requestMessage != "I AM READY" {
+ lastRide, err := c.svc.Rides.GetLastRideByPhoneNumber(twilioResponse.From, "", "")
+ if err != nil {
+ fmt.Println("Error to get the ride: ", err.Error())
+ }
+
+ notifications := make([]viewmodel.Notification, 0)
+ notifications = append(notifications, c.svc.Notification.GetNotification(lastRide, "sms", "Message to Dispatcher", twilioResponse.Body, true, "message"))
+ notifications = append(notifications, c.svc.Notification.GetNotification(lastRide, "app", "Message to Dispatcher", twilioResponse.Body, true, "message"))
+ notifications, err = c.svc.Notification.SendNotifications(notifications)
+ if err != nil {
+ fmt.Println("Error to notify: ", err.Error())
+ }
+ } else {
+ toNumber := twilioResponse.From
+
+ var message string
+ var lastRide viewmodel.Ride
+ isDriver := false
+
+ num, _ := libphonenumber.Parse(twilioResponse.From, "US")
+ if strings.HasPrefix(requestMessage, "MEMBER") {
+ isDriver = true
+ lastRide, err = c.svc.Rides.GetLastRideByDriversNumber(twilioResponse.From)
+ if err != nil {
+ fmt.Println("Error to get last driver ride: ", err.Error())
+ message = fmt.Sprintf("We received a request to cancel a ride from you at %s, but cannot find a ride for this mobile number.", libphonenumber.Format(num, libphonenumber.NATIONAL))
+ }
+ } else {
+ lastRide, err = c.svc.Rides.GetLastRideByPhoneNumber(twilioResponse.From, "", "")
+ if err != nil {
+ fmt.Println("Error to get last ride: ", err.Error())
+ message = fmt.Sprintf("We received a request to cancel a ride from you at %s, but cannot find a ride for this mobile number.", libphonenumber.Format(num, libphonenumber.NATIONAL))
+ }
+ }
+ if !isDriver {
+ if requestMessage == "I AM READY" && lastRide.UUID != "" {
+ if (lastRide.Visit.TripType.Key == "roundtrip_call" && (lastRide.TripType.Key == "to_visit" || lastRide.TripType.Key == "from_visit_call")) || lastRide.Visit.TripType.Key == "from_visit_call" {
+ var readyRide viewmodel.Ride
+ authUser, err := c.svc.Users.GetByUUID(lastRide.CreatedUser.ID, "")
+ if err != nil {
+ fmt.Println("Error to get created user: ", err.Error())
+ }
+
+ if lastRide.TripType.Key == "to_visit" {
+ readyRide, err = c.svc.Rides.GetByVisitUUIDAndTripType(lastRide.Visit.UUID, "from_visit_call", authUser)
+ if err != nil || readyRide.UUID == "" {
+ message = fmt.Sprintf("We received a request to send the return ride from you at %s, but you do not have the a return ride prepared.", libphonenumber.Format(num, libphonenumber.NATIONAL))
+ }
+ } else {
+ readyRide = lastRide
+ }
+
+ switch readyRide.Status.Key {
+ case "pending", "accepted", "scheduled":
+ message = "We already request your return ride, you should receive updates soon."
+ case "willCall":
+ var lyftRide viewmodel.RideRequest
+ lyftRide.RideID = ""
+ lyftRide.Destination = readyRide.Route.Destination
+ lyftRide.Origin = readyRide.Route.Origin
+ name := readyRide.User.Name
+ names := strings.Split(name, " ")
+ lyftRide.Passenger.FirstName = names[0]
+ lyftRide.Passenger.LastName = " "
+ lyftRide.Passenger.PhoneNumber = *readyRide.User.PhoneNumber
+ lyftRide.RideType = "lyft"
+
+ if c.cfg.LyftProd.UserUUID != readyRide.CreatedUser.ID {
+ lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.RequestRide(lyftRide)
+ }
+ if err != nil {
+ fmt.Println("Error to create a lyft ride on twilio: ", err.Error())
+ message = "There was a problem to call your ride"
+ }
+
+ readyRide, err = c.svc.Rides.UpdateNewRide(readyRide, lyftRide, authUser)
+ if err != nil {
+ fmt.Println("Error to update ride: ", err.Error())
+ message = "There was a problem to call your ride"
+ }
+
+ go func() {
+ err = c.svc.Notification.SendNotification(readyRide.Status.Key, readyRide, lyftRide)
+ if err != nil {
+ fmt.Println("Error to notify user: ", err.Error())
+ }
+ }()
+
+ message = fmt.Sprintf("Ride requested at %s, for pickup at %s.", lyftRide.RequestAt.Format("03:04 PM"), readyRide.Route.Destination.Name)
+ }
+
+ }
+ }
+
+ if requestMessage == "CANCEL RIDE" && lastRide.UUID != "" {
+ var visitDate time.Time
+ if lastRide.VisitTime != nil {
+ visitDate = *lastRide.VisitTime
+ } else {
+ visitDate = *lastRide.VisitDate
+ }
+
+ var pickupDate time.Time
+ if lastRide.PickupTime != nil {
+ pickupDate = *lastRide.PickupTime
+ }
+
+ message = fmt.Sprintf("Are you sure you want to cancel a ride to %s visit to %s scheduled for %s?\nReply YES to confirm this cancellation", visitDate.Format("01/02/2006 03:04 PM"), lastRide.Route.Destination.Name, pickupDate.Format("03:04 PM"))
+ }
+
+ if requestMessage == "YES" && lastRide.UUID != "" {
+ var lyftRide viewmodel.RideRequest
+ if lastRide.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
+ lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: lastRide.InternalID})
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ message = "There was a problem to find your ride"
+ }
+
+ if err = c.tnc.Lyft.CancelRide(lyftRide); err != nil {
+ fmt.Println("Error to cancel with Lyft: ", err.Error())
+ message = "There was a problem to cancel your ride with our transportation provider"
+ }
+ } else {
+ fmt.Println("In Production")
+ lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: lastRide.InternalID})
+ if err != nil {
+ fmt.Println("Error: ", err.Error())
+ message = "There was a problem to find your ride"
+ }
+
+ if err = c.tnc.LyftProd.CancelRide(lyftRide); err != nil {
+ fmt.Println("Error to cancel with Lyft: ", err.Error())
+ message = "There was a problem to cancel your ride with our transportation provider"
+ }
+ }
+
+ if err = c.svc.Rides.UpdateStatus(lastRide.UUID, "canceled"); err != nil {
+ fmt.Println("Error to cancel the ride: ", err.Error())
+ message = "There was a problem to cancel your ride on our systems"
+ }
+
+ var dateToFormat time.Time
+ if lastRide.VisitTime != nil {
+ dateToFormat = *lastRide.VisitTime
+ } else {
+ dateToFormat = *lastRide.VisitDate
+ }
+
+ var pickupDate time.Time
+ if lastRide.PickupTime != nil {
+ pickupDate = *lastRide.PickupTime
+ }
+ lastRide.Status.Key = "cancelled"
+ message = fmt.Sprintf("A ride to a %s visit to %s scheduled for %s has been cancelled.", dateToFormat.Format("01/02/2006 03:04 PM"), lastRide.Route.Destination.Name, pickupDate.Format("03:04 PM"))
+ }
+
+ // if requestMessage == "NO" && lastRide.UUID != "" {
+ // var dateToFormat time.Time
+ // if lastRide.VisitTime != nil {
+ // dateToFormat = *lastRide.VisitTime
+ // } else {
+ // dateToFormat = *lastRide.VisitDate
+ // }
+ // message = fmt.Sprintf("You ride is still scheduled on %s at %s", lastRide.Route.Destination.Name, dateToFormat.Format("01/02/2006 03:04 PM"))
+ // }
+
+ if strings.HasPrefix(requestMessage, "DRIVER") && lastRide.UUID != "" {
+ driverMessage := strings.Replace(requestMessage, "DRIVER", "", -1)
+ driverMessage = strings.TrimSpace(driverMessage) + "\nReply MEMBER and your message to send a message to the member."
+
+ notifications := make([]viewmodel.Notification, 0)
+ notifications = append(notifications, c.getDriverNotification(lastRide, "sms", "Message to the driver", driverMessage, lastRide.Driver.PhoneNumber, twilioResponse.To))
+ notifications = append(notifications, c.getDriverNotification(lastRide, "sms", "Message to the driver", requestMessage, *lastRide.CreatedUser.PhoneNumber, *lastRide.User.PhoneNumber))
+ notifications = append(notifications, c.getDriverNotification(lastRide, "email", "Message to the driver", driverMessage, *lastRide.CreatedUser.Email, *lastRide.User.Email))
+ notifications, err := c.svc.Notification.SendNotifications(notifications)
+ if err != nil {
+ message = "There was a problem to send a message to the driver."
+ fmt.Println("Error to send drivers notification: ", err.Error())
+ }
+
+ message = "Your message was sent to the driver via SMS."
+ }
+ } else {
+ driverMessage := strings.Replace(requestMessage, "MEMBER", "", -1)
+ driverMessage = strings.TrimSpace(driverMessage) + "\nReply DRIVER and your message to send a message to the driver."
+
+ userPhoneNumber := ""
+ createUserPhoneNumber := ""
+ userEmail := ""
+ createdUserEmail := ""
+ if lastRide.User.PhoneNumber != nil {
+ userPhoneNumber = *lastRide.User.PhoneNumber
+ }
+
+ if lastRide.CreatedUser.PhoneNumber != nil {
+ createUserPhoneNumber = *lastRide.CreatedUser.PhoneNumber
+ }
+
+ if lastRide.User.Email != nil {
+ userEmail = *lastRide.User.Email
+ }
+
+ if lastRide.CreatedUser.Email != nil {
+ createdUserEmail = *lastRide.CreatedUser.Email
+ }
+
+ notifications := make([]viewmodel.Notification, 0)
+ notifications = append(notifications, c.getDriverNotification(lastRide, "sms", "Message to the member from the driver", driverMessage, userPhoneNumber, twilioResponse.To))
+ notifications = append(notifications, c.getDriverNotification(lastRide, "sms", "Message to the member from the driver", requestMessage, createUserPhoneNumber, userPhoneNumber))
+ notifications = append(notifications, c.getDriverNotification(lastRide, "email", "Message to the member from the driver", driverMessage, createdUserEmail, userEmail))
+ notifications, err := c.svc.Notification.SendNotifications(notifications)
+ if err != nil {
+ message = "There was a problem to send a message to the member."
+ fmt.Println("Error to send member notification: ", err.Error())
+ }
+
+ message = "Your message was sent to the member via SMS."
+ }
+ resp.Message = &Message{
+ To: toNumber,
+ Body: message,
+ }
+ }
+ return ctx.XML(http.StatusOK, resp)
+}
+
+func (c *controller) handleMessages() {
+ for {
+ msg := <-c.broadcast
+ for client := range c.clients {
+ if c.clients[client].From == msg.To {
+ err := client.WriteJSON(msg)
+ if err != nil {
+ log.Printf("error: %v", err)
+ client.Close()
+ delete(c.clients, client)
+ }
+ }
+ }
+ }
+}
+
+func (c *controller) handleSocket(ctx echo.Context) error {
+ ws, err := upgrader.Upgrade(ctx.Response(), ctx.Request(), nil)
+ if err != nil {
+ return err
+ }
+ defer ws.Close()
+
+ c.clients[ws] = viewmodel.SocketMessage{Filled: false}
+ for {
+ var msg viewmodel.SocketMessage
+ err := ws.ReadJSON(&msg)
+ if err != nil {
+ log.Printf("error: %v", err)
+ delete(c.clients, ws)
+ break
+ }
+ msg.Filled = true
+ c.clients[ws] = msg
+ }
+ return nil
+}
diff --git a/server/router/twilioroute/router.go b/server/router/twilioroute/router.go
new file mode 100644
index 0000000..4f4920c
--- /dev/null
+++ b/server/router/twilioroute/router.go
@@ -0,0 +1,21 @@
+package twilioroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = ""
+ wsRoute = "/ws"
+)
+
+// Register authenticate route
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) {
+ ctrl := controllerInstance(cfg, svc, tnc, notification)
+ r.POST(rootRoute, ctrl.handleTwilio)
+ r.GET(wsRoute, ctrl.handleSocket)
+}
diff --git a/server/router/usersroute/controller.go b/server/router/usersroute/controller.go
new file mode 100644
index 0000000..833bd5e
--- /dev/null
+++ b/server/router/usersroute/controller.go
@@ -0,0 +1,444 @@
+package usersroute
+
+import (
+ b64 "encoding/base64"
+ "fmt"
+ "math/rand"
+ "sync"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/domain"
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/cache"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ svc *applicationservice.Service
+ cfg *config.Config
+}
+
+func controllerInstance(svc *applicationservice.Service, cfg *config.Config) *controller {
+ once.Do(func() {
+ instance = &controller{
+ svc: svc,
+ cfg: cfg,
+ }
+ })
+ return instance
+}
+
+func (c *controller) handleGetAll(ctx echo.Context) error {
+ page, quantity := routeutils.GetPagingParams(ctx)
+
+ list, err := c.svc.Users.GetAll(quantity, page)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, list)
+}
+
+func (c *controller) handleGetByID(ctx echo.Context) error {
+ userID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "mandatory field")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ authUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ item, err := c.svc.Users.GetByUUID(userID, "US")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ rides, err := c.svc.Rides.GetByUserUUID(userID, authUser)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ item.Rides = rides
+
+ return routeutils.ResponseAPIOK(ctx, item)
+}
+
+func (c *controller) handlePortalAddress(ctx echo.Context) error {
+ userID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "mandatory field")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ item, err := c.svc.Users.GetByUUID(userID, "")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ createdUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if item.ID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "User not found")
+ } else {
+ var Address viewmodel.Address
+ if err := ctx.Bind(&Address); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ Address.User = item
+ Address.CreatedUserUUID = createdUser.ID
+ Address, err = c.svc.Users.SaveAddress(Address)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ Address.User, err = c.svc.Users.GetByUUID(userID, "")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, Address)
+ }
+}
+
+func (c *controller) handleRemoveAddress(ctx echo.Context) error {
+ addressID, err := routeutils.GetAndValidateStringParam(ctx, "address_uuid", "mandatory field")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ err = c.svc.Users.RemoveAddress(addressID)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseNoContent(ctx, addressID)
+}
+
+func (c *controller) handleMemberAddress(ctx echo.Context) error {
+ userID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "mandatory field")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ item, err := c.svc.Users.GetByUUID(userID, "")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ createdUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if item.ID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "User not found")
+ } else {
+ var Address viewmodel.Address
+ if err := ctx.Bind(&Address); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ Address.User = item
+ Address.CreatedUserUUID = createdUser.ID
+ Address, err = c.svc.Users.SaveAddress(Address)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ Address.User, err = c.svc.Users.GetByUUID(userID, "US")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, Address)
+ }
+}
+
+func (c *controller) handleMemberDetail(ctx echo.Context) error {
+ userID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "mandatory field")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ authUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ item, err := c.svc.Users.GetByUUID(userID, "US")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ rides, err := c.svc.Rides.GetByUserUUID(userID, authUser)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ item.Rides = rides
+
+ if item.ID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "User not found")
+ } else {
+ return routeutils.ResponseAPIOK(ctx, item)
+ }
+}
+
+func (c *controller) handlePortalDetail(ctx echo.Context) error {
+ userID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "mandatory field")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ item, err := c.svc.Users.GetByUUID(userID, "SP")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if item.ID == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "User not found")
+ } else {
+ return routeutils.ResponseAPIOK(ctx, item)
+ }
+}
+
+func (c *controller) stringWithCharset(length int, charset string) string {
+ b := make([]byte, length)
+ var seededRand *rand.Rand = rand.New(
+ rand.NewSource(time.Now().UnixNano()))
+ for i := range b {
+ b[i] = charset[seededRand.Intn(len(charset))]
+ }
+ return string(b)
+}
+
+func (c *controller) generatePassword(n int) string {
+ const (
+ charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ )
+
+ return c.stringWithCharset(n, charset)
+}
+
+func (c *controller) handleGetMember(ctx echo.Context) error {
+ users, err := c.svc.Users.GetUsersByProfile("US")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ authUser, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ rides, err := c.svc.Rides.GetAll(authUser)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ for i := range users {
+ for _, r := range rides {
+ if r.User.ID == users[i].ID {
+ users[i].Rides = append(users[i].Rides, r)
+ }
+ }
+ }
+
+ return routeutils.ResponseAPIOK(ctx, users)
+}
+
+func (c *controller) handleGetPortal(ctx echo.Context) error {
+ users, err := c.svc.Users.GetUsersByProfile("")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, users)
+}
+
+func (c *controller) handleMember(ctx echo.Context) error {
+ var user viewmodel.User
+ if err := ctx.Bind(&user); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if user.PhoneNumber == nil && user.Email == nil || len(*user.PhoneNumber) == 0 && len(*user.Email) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "phonenumber or email is required", false)
+ }
+
+ if len(user.Pass) == 0 {
+ user.Pass = c.generatePassword(8)
+ } else {
+ pass, err := b64.StdEncoding.DecodeString(user.Pass)
+ if err != nil {
+ return routeutils.ResponseAPIAuthError(ctx, "Invalid password", false)
+ }
+ user.Pass = string(pass)
+ }
+
+ if user.BirthDate == nil || user.BirthDate.IsZero() {
+ return routeutils.ResponseAPIAuthError(ctx, "birthdate is required", false)
+ }
+
+ if user.Member == nil || len(*user.Member) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "member is required", false)
+ }
+
+ if user.Gender == nil || len(*user.Gender) == 0 || (*user.Gender != "M" && *user.Gender != "F" && *user.Gender != "U") {
+ return routeutils.ResponseAPIAuthError(ctx, "gender is required", false)
+ }
+
+ if len(user.Name) == 0 && len(user.First) == 0 && len(user.Last) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
+ }
+
+ if len(user.First) != 0 && len(user.Last) != 0 {
+ user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
+ }
+
+ profile, err := c.svc.Profile.GetByKey("US")
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ user.Profiles = append(user.Profiles, profile)
+
+ user, err = c.svc.Users.Create(user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, user)
+}
+
+func (c *controller) handleBulkPortal(ctx echo.Context) error {
+ var users []viewmodel.User
+ if err := ctx.Bind(&users); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ for i, _ := range users {
+ if len(users[i].Profiles) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "profile is required", false)
+ }
+
+ if users[i].PhoneNumber == nil || len(*users[i].PhoneNumber) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "phonenumber is required", false)
+ }
+
+ if users[i].Email == nil || len(*users[i].Email) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "email is required", false)
+ }
+
+ if len(users[i].Pass) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "password is required", false)
+ }
+
+ pass, err := b64.StdEncoding.DecodeString(users[i].Pass)
+ if err != nil {
+ return routeutils.ResponseAPIAuthError(ctx, "Invalid password", false)
+ }
+ users[i].Pass = string(pass)
+
+ if len(users[i].Name) == 0 && len(users[i].First) == 0 && len(users[i].Last) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
+ }
+
+ if len(users[i].First) != 0 && len(users[i].Last) != 0 {
+ users[i].Name = fmt.Sprintf("%s %s", users[i].First, users[i].Last)
+ }
+ }
+
+ returnUser, err := c.svc.Users.CreateBulk(users)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, returnUser)
+}
+
+func (c *controller) handlePortal(ctx echo.Context) error {
+ var user viewmodel.User
+ if err := ctx.Bind(&user); err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ if len(user.Profiles) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "profile is required", false)
+ }
+
+ if user.PhoneNumber == nil || len(*user.PhoneNumber) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "phonenumber is required", false)
+ }
+
+ if user.Email == nil || len(*user.Email) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "email is required", false)
+ }
+
+ if len(user.Pass) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "password is required", false)
+ }
+
+ pass, err := b64.StdEncoding.DecodeString(user.Pass)
+ if err != nil {
+ return routeutils.ResponseAPIAuthError(ctx, "Invalid password", false)
+ }
+ user.Pass = string(pass)
+
+ if len(user.Name) == 0 && len(user.First) == 0 && len(user.Last) == 0 {
+ return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
+ }
+
+ if len(user.First) != 0 && len(user.Last) != 0 {
+ user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
+ }
+
+ user, err = c.svc.Users.Create(user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, user)
+}
+
+func (c *controller) handleContactType(ctx echo.Context) error {
+
+ cache := cache.Instance(c.cfg)
+ cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
+ resp := []viewmodel.ContactType{}
+
+ err := cache.GetStruct(cacheKey, &resp)
+
+ if err != nil {
+ if err != domain.ErrCacheMiss {
+ ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
+ }
+ resp, err = c.svc.Users.GetContactType()
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+ cache.SetStruct(cacheKey, resp)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleTokenInfo(ctx echo.Context) error {
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, user)
+}
diff --git a/server/router/usersroute/router.go b/server/router/usersroute/router.go
new file mode 100644
index 0000000..57fe11c
--- /dev/null
+++ b/server/router/usersroute/router.go
@@ -0,0 +1,54 @@
+package usersroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = "/"
+ idRoute = "/:user_uuid/"
+ memberRoute = "/member"
+ memberDetailRoute = "/member/:user_uuid"
+ memberAddressRoute = "/member/:user_uuid/address"
+ memberRemoveAddressRoute = "/member/:user_uuid/address/:address_uuid"
+ userRoute = "/portal"
+ userDetailRoute = "/portal/:user_uuid"
+ userAddressRoute = "/portal/:user_uuid/address"
+ userRemoveAddressRoute = "/portal/:user_uuid/address/:address_uuid"
+ portalRoute = "/portal"
+ portalBulkRoute = "/portal/bulk"
+ contacttypeRoute = "/contacttype"
+
+ tokenInfoRoute = "/tokeninfo"
+)
+
+// Register registers the routes in the echo group
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(svc, cfg)
+
+ r.GET(rootRoute, ctrl.handleGetAll)
+ r.GET(idRoute, ctrl.handleGetByID)
+
+ r.POST(memberAddressRoute, ctrl.handleMemberAddress)
+ r.PUT(memberRemoveAddressRoute, ctrl.handleRemoveAddress)
+ r.GET(memberDetailRoute, ctrl.handleMemberDetail)
+ r.GET(memberRoute, ctrl.handleGetMember)
+
+ r.GET(userDetailRoute, ctrl.handlePortalDetail)
+ r.GET(userRoute, ctrl.handleGetPortal)
+ r.POST(userAddressRoute, ctrl.handlePortalAddress)
+ r.PUT(userRemoveAddressRoute, ctrl.handleRemoveAddress)
+
+ //Can be cached
+ r.GET(contacttypeRoute, ctrl.handleContactType)
+
+ r.POST(memberRoute, ctrl.handleMember)
+ r.POST(portalRoute, ctrl.handlePortal)
+ r.POST(portalBulkRoute, ctrl.handleBulkPortal)
+
+ if cfg.App.Debug {
+ r.GET(tokenInfoRoute, ctrl.handleTokenInfo)
+ }
+}
diff --git a/server/router/visitroute/controller.go b/server/router/visitroute/controller.go
new file mode 100644
index 0000000..dd93e70
--- /dev/null
+++ b/server/router/visitroute/controller.go
@@ -0,0 +1,64 @@
+package visitroute
+
+import (
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *controller
+ once sync.Once
+)
+
+type controller struct {
+ svc *applicationservice.Service
+ cfg *config.Config
+}
+
+func controllerInstance(svc *applicationservice.Service, cfg *config.Config) *controller {
+ once.Do(func() {
+ instance = &controller{
+ svc: svc,
+ cfg: cfg,
+ }
+ })
+ return instance
+}
+
+func (c *controller) handleGetByID(ctx echo.Context) error {
+ visit_uuid := ctx.Param("visit_uuid")
+ if visit_uuid == "" {
+ return routeutils.ResponseAPIValidationError(ctx, "visit_uuid param is mandatory")
+ }
+
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Visits.GetByUUID(visit_uuid, user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
+
+func (c *controller) handleGetAll(ctx echo.Context) error {
+ user, err := auth.GetUserDetail(ctx, c.cfg)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ resp, err := c.svc.Visits.GetAll(user)
+ if err != nil {
+ return routeutils.HandleAPIError(ctx, err)
+ }
+
+ return routeutils.ResponseAPIOK(ctx, resp)
+}
diff --git a/server/router/visitroute/router.go b/server/router/visitroute/router.go
new file mode 100644
index 0000000..62724ba
--- /dev/null
+++ b/server/router/visitroute/router.go
@@ -0,0 +1,20 @@
+package visitroute
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+)
+
+const (
+ rootRoute = "/"
+ idRoute = "/:visit_uuid"
+)
+
+// Register registers the routes in the echo group
+func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
+ ctrl := controllerInstance(svc, cfg)
+
+ r.GET(rootRoute, ctrl.handleGetAll)
+ r.GET(idRoute, ctrl.handleGetByID)
+}
diff --git a/server/server.go b/server/server.go
new file mode 100644
index 0000000..bb3202a
--- /dev/null
+++ b/server/server.go
@@ -0,0 +1,73 @@
+package server
+
+import (
+ "fmt"
+ "sync"
+
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
+ "bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/tncservice"
+ "bitbucket.org/nemt/nemt-portal-api/domain/contract"
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "bitbucket.org/nemt/nemt-portal-api/infra/logger"
+ "bitbucket.org/nemt/nemt-portal-api/server/router"
+ "bitbucket.org/nemt/nemt-portal-api/server/serverconfig"
+ "github.com/labstack/echo"
+)
+
+var (
+ instance *Server
+ once sync.Once
+)
+
+// Server runs the application
+type Server struct {
+ srv *echo.Echo
+ svc *service.Service
+ cfg *config.Config
+ log *logger.Logger
+ cache contract.CacheManager
+}
+
+// Instance returns an instance of Service
+func Instance(svc *service.Service, cfg *config.Config, log *logger.Logger, cache contract.CacheManager) *Server {
+ once.Do(func() {
+ instance = &Server{
+ srv: echo.New(),
+ svc: svc,
+ cfg: cfg,
+ log: log,
+ cache: cache,
+ }
+ })
+ return instance
+}
+
+// Run setup and executes the server
+func (s *Server) Run() error {
+ s.srv.HideBanner = true
+
+ s.srv.Debug = s.cfg.App.Debug
+
+ err := serverconfig.SetMiddlewares(s.srv, s.cfg, s.log, s.svc)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ entityMapper := entitymapping.New()
+ notificationService := notificationservice.New(s.svc, entityMapper, s.cfg, s.cache)
+ appService := applicationservice.New(s.svc, entityMapper, notificationService, s.cfg)
+ tncService := tncservice.New(s.svc, entityMapper, s.cfg, notificationService)
+
+ router.Register(s.srv, s.cfg, appService, tncService, notificationService)
+
+ err = s.srv.Start(fmt.Sprintf(":%d", s.cfg.HTTP.Port))
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
diff --git a/server/serverconfig/auth.go b/server/serverconfig/auth.go
new file mode 100644
index 0000000..53c2d66
--- /dev/null
+++ b/server/serverconfig/auth.go
@@ -0,0 +1,25 @@
+package serverconfig
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+func setJWTMiddleware(e *echo.Echo, cfg *config.Config) error {
+ key, err := auth.GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ e.Pre(middlewareErrorWrapper(middleware.JWTWithConfig(middleware.JWTConfig{
+ TokenLookup: "header:" + auth.AppTokenHeaderName,
+ Skipper: authSkipper,
+ SigningKey: key,
+ SigningMethod: auth.TokenSigningMethod.Name,
+ })))
+
+ return nil
+}
diff --git a/server/serverconfig/authorization.go b/server/serverconfig/authorization.go
new file mode 100644
index 0000000..ee59064
--- /dev/null
+++ b/server/serverconfig/authorization.go
@@ -0,0 +1,93 @@
+package serverconfig
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
+ "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
+ "bitbucket.org/nemt/nemt-portal-api/infra/auth"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/logger"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/casbin/casbin"
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+
+ "strings"
+)
+
+type (
+ // Config defines the config for CasbinAuth middleware.
+ Config struct {
+ // Skipper defines a function to skip middleware.
+ Skipper middleware.Skipper
+
+ // Enforcer CasbinAuth main rule.
+ // Required.
+ Enforcer *casbin.Enforcer
+
+ Application *config.Config
+
+ Svc *applicationservice.Service
+ Logger *logger.Logger
+ }
+)
+
+var (
+ // DefaultConfig is the default CasbinAuth middleware config.
+ DefaultConfig = Config{
+ Skipper: middleware.DefaultSkipper,
+ }
+)
+
+// MiddlewareWithConfig returns a CasbinAuth middleware with config.
+// See `Middleware()`.
+func MiddlewareWithConfig(cfg *config.Config, svc *applicationservice.Service, log *logger.Logger) echo.MiddlewareFunc {
+
+ config := &DefaultConfig
+
+ config.Svc = svc
+ config.Logger = log
+ config.Application = cfg
+
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ if config.Skipper(c) || config.CheckPermission(c) {
+ return next(c)
+ }
+
+ return routeutils.HandleHTMLError(c, echo.ErrForbidden)
+ }
+ }
+}
+
+func setAuthorizationMiddleware(e *echo.Echo, log *logger.Logger, cfg *config.Config, svc *applicationservice.Service) {
+ e.Use(MiddlewareWithConfig(cfg, svc, log))
+}
+
+// CheckPermission checks the user/method/path combination from the request.
+// Returns true (permission granted) or false (permission forbidden)
+func (a *Config) CheckPermission(c echo.Context) bool {
+ user, err := auth.GetUserDetail(c, a.Application)
+ if err != nil {
+ a.Logger.Warningf("Cannot get user details. %v ", err)
+ }
+ method := c.Request().Method
+ path := c.Request().URL.Path
+ //objectOrganization := a.organizationGoverningObject(c, user)
+
+ return a.Enforcer.Enforce(user, path, method)
+}
+
+func (a *Config) organizationGoverningObject(c echo.Context, userDetails viewmodel.User) (result viewmodel.Organization) {
+
+ existingUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) > 0
+ newUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) <= 0
+
+ switch {
+ case existingUser:
+ user, _ := a.Svc.Users.GetByUUID(c.ParamValues()[0], "")
+ result = user.Organizations[0]
+ case newUser:
+ result = userDetails.Organizations[0]
+ }
+ return
+}
diff --git a/server/serverconfig/authorization_model.conf b/server/serverconfig/authorization_model.conf
new file mode 100644
index 0000000..5f72726
--- /dev/null
+++ b/server/serverconfig/authorization_model.conf
@@ -0,0 +1,11 @@
+[request_definition]
+r = role, obj, act
+
+[policy_definition]
+p = role, obj, act
+
+[policy_effect]
+e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
+
+[matchers]
+m = keymatch(r.role, p.role) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
\ No newline at end of file
diff --git a/server/serverconfig/bodylimit.go b/server/serverconfig/bodylimit.go
new file mode 100644
index 0000000..9b33f7c
--- /dev/null
+++ b/server/serverconfig/bodylimit.go
@@ -0,0 +1,10 @@
+package serverconfig
+
+import (
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+func setBodyLimitMiddleware(e *echo.Echo) {
+ e.Use(middleware.BodyLimit("4M"))
+}
diff --git a/server/serverconfig/cache.go b/server/serverconfig/cache.go
new file mode 100644
index 0000000..90af1f7
--- /dev/null
+++ b/server/serverconfig/cache.go
@@ -0,0 +1,204 @@
+package serverconfig
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "regexp"
+ "strings"
+
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/domain"
+ "bitbucket.org/nemt/nemt-portal-api/infra/cache"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+// bodyResponseWriter implements the http.ResponseWriter interface
+type bodyResponseWriter struct {
+ io.Writer
+ http.ResponseWriter
+}
+
+func (w *bodyResponseWriter) WriteHeader(code int) {
+ w.ResponseWriter.WriteHeader(code)
+}
+
+func (w *bodyResponseWriter) Write(b []byte) (int, error) {
+ return w.Writer.Write(b)
+}
+
+func (w *bodyResponseWriter) Flush() {
+ w.ResponseWriter.(http.Flusher).Flush()
+}
+
+func (w *bodyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ return w.ResponseWriter.(http.Hijacker).Hijack()
+}
+
+func (w *bodyResponseWriter) CloseNotify() <-chan bool {
+ return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
+
+// CacheConfig defines the config for Cache middleware.
+type CacheConfig struct {
+ // Skipper determines if the request should skip this middleware
+ Skipper middleware.Skipper
+ // Cache expiration/lifetime
+ Expiration time.Duration
+ // VaryByQuery contains a list of query parameters to include in cache key
+ VaryByQuery []string
+}
+
+// DefaultCacheConfig is the default Cache middleware config.
+var DefaultCacheConfig = CacheConfig{
+ Skipper: middleware.DefaultSkipper,
+}
+
+// CacheMiddleware returns a middleware that protects requests agains Cache attacks.
+func CacheMiddleware(cfg *config.Config) echo.MiddlewareFunc {
+ config := DefaultCacheConfig
+ config.Expiration = cfg.Cache.DefaultExpiration
+
+ return CacheMiddlewareWithConfig(cfg, config)
+}
+
+// CacheMiddlewareWithConfig returns a Cache middleware with config.
+// See: `CacheMiddleware()`.
+func CacheMiddlewareWithConfig(cfg *config.Config, config CacheConfig) echo.MiddlewareFunc {
+ if config.Skipper == nil {
+ config.Skipper = DefaultCacheConfig.Skipper
+ }
+
+ if config.Expiration < 0 {
+ config.Expiration = cfg.Cache.DefaultExpiration
+ }
+
+ cache := cache.Instance(cfg)
+
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ req := c.Request()
+
+ skip := config.Skipper(c) || req.Method != echo.GET
+
+ if !skip {
+ for _, val := range req.Header["Cache-Control"] {
+ if val == "no-cache" {
+ skip = true
+ break
+ }
+ }
+ }
+
+ if skip {
+ return next(c)
+ }
+
+ res := c.Response()
+
+ var cacheKey = getCacheKey(c, config)
+ var contentTypeCacheKey = fmt.Sprintf("%s-content-type", cacheKey)
+ var contentType = "application/json"
+
+ output, err := cache.GetItem(cacheKey)
+ if err == nil {
+ var responseStatus = http.StatusOK
+
+ if len(output) == 0 {
+ responseStatus = http.StatusNoContent
+ }
+
+ contentType, err = cache.GetString(contentTypeCacheKey)
+ if err != nil {
+ return routeutils.HandleAPIError(c, err)
+ }
+
+ expiration, err := cache.GetExpiration(cacheKey)
+ if err != nil {
+ return routeutils.HandleAPIError(c, err)
+ }
+
+ if expiration > 0 {
+ res.Header()["Cache-Control"] = []string{fmt.Sprintf("max-age=%v", expiration.Seconds())}
+ }
+
+ return c.Blob(responseStatus, contentType, []byte(output))
+ } else if err == domain.ErrCacheMiss {
+ resBody := new(bytes.Buffer)
+
+ mw := io.MultiWriter(res.Writer, resBody)
+
+ writer := &bodyResponseWriter{Writer: mw, ResponseWriter: res.Writer}
+
+ res.Writer = writer
+
+ err = next(c)
+ if err != nil {
+ return err
+ }
+
+ headers := writer.Header()
+
+ cache.SetExpiration(cacheKey, config.Expiration)
+
+ if config.Expiration != 0 {
+ res.Header()["Cache-Control"] = []string{fmt.Sprintf("max-age=%v", config.Expiration.Seconds())}
+ }
+
+ contentTypeHeader, ok := headers[echo.HeaderContentType]
+ if ok {
+ contentType = contentTypeHeader[0]
+ }
+
+ err = cache.SetItem(cacheKey, resBody.Bytes())
+ if err != nil {
+ return routeutils.HandleAPIError(c, err)
+ }
+ err = cache.SetString(contentTypeCacheKey, contentType)
+ if err != nil {
+ return routeutils.HandleAPIError(c, err)
+ }
+ } else if err != nil {
+ return routeutils.HandleAPIError(c, err)
+ }
+
+ return nil
+ }
+ }
+}
+
+func getCacheKey(c echo.Context, config CacheConfig) string {
+ var req = c.Request()
+
+ var re = regexp.MustCompile("(?i)[^a-z0-9_]+")
+
+ var key = req.URL.Path
+
+ if len(config.VaryByQuery) > 0 {
+ var query = "q"
+
+ for _, queryKey := range config.VaryByQuery {
+ for k, v := range req.URL.Query() {
+ if k == queryKey {
+ query = fmt.Sprintf("%s-%s-%s", query, k, v)
+ break
+ }
+ }
+ }
+
+ query = strings.Trim(re.ReplaceAllString(query, "-"), "-")
+
+ if strings.TrimSpace(query) != "" {
+ key = fmt.Sprintf("%s-%v", key, query)
+ }
+ }
+
+ return strings.Trim(re.ReplaceAllString(key, "-"), "-")
+}
diff --git a/server/serverconfig/cors.go b/server/serverconfig/cors.go
new file mode 100644
index 0000000..e077f65
--- /dev/null
+++ b/server/serverconfig/cors.go
@@ -0,0 +1,17 @@
+package serverconfig
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+func setCORSMiddleware(e *echo.Echo, cfg *config.Config) {
+ middlewareConfig := middleware.DefaultCORSConfig
+
+ if !cfg.App.Debug {
+ middlewareConfig.AllowOrigins = cfg.HTTP.Auth.FrontendURLs
+ }
+
+ e.Pre(middleware.CORSWithConfig(middlewareConfig))
+}
diff --git a/server/serverconfig/gzip.go b/server/serverconfig/gzip.go
new file mode 100644
index 0000000..60eea6d
--- /dev/null
+++ b/server/serverconfig/gzip.go
@@ -0,0 +1,10 @@
+package serverconfig
+
+import (
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+func setGZIPMiddleware(e *echo.Echo) {
+ e.Use(middleware.Gzip())
+}
diff --git a/server/serverconfig/log.go b/server/serverconfig/log.go
new file mode 100644
index 0000000..e0cf5ee
--- /dev/null
+++ b/server/serverconfig/log.go
@@ -0,0 +1,151 @@
+package serverconfig
+
+import (
+ "encoding/json"
+ "io"
+ "strconv"
+ "time"
+
+ "bitbucket.org/nemt/nemt-portal-api/infra/logger"
+ "github.com/Sirupsen/logrus"
+ "github.com/labstack/echo"
+ "github.com/labstack/gommon/log"
+)
+
+type echoLogger struct {
+ *logger.Logger
+}
+
+// Printj prints a message in json format
+func (l *echoLogger) Printj(data log.JSON) {
+ bytes, _ := json.Marshal(data)
+ l.Logger.Print(string(bytes))
+}
+
+// Debugj logs a debug message in json format
+func (l *echoLogger) Debugj(data log.JSON) {
+ bytes, _ := json.Marshal(data)
+ l.Logger.Debug(string(bytes))
+}
+
+// Infoj logs an info message in json format
+func (l *echoLogger) Infoj(data log.JSON) {
+ bytes, _ := json.Marshal(data)
+ l.Logger.Info(string(bytes))
+}
+
+// Warnj logs a warning message in json format
+func (l *echoLogger) Warnj(data log.JSON) {
+ bytes, _ := json.Marshal(data)
+ l.Logger.Warn(string(bytes))
+}
+
+// Errorj logs an error message in json format
+func (l *echoLogger) Errorj(data log.JSON) {
+ bytes, _ := json.Marshal(data)
+ l.Logger.Error(string(bytes))
+}
+
+// Panicj logs a panic message in json format
+func (l *echoLogger) Panicj(data log.JSON) {
+ bytes, _ := json.Marshal(data)
+ l.Logger.Panic(string(bytes))
+}
+
+// Fatalj logs a fatal message in json format
+func (l *echoLogger) Fatalj(data log.JSON) {
+ bytes, _ := json.Marshal(data)
+ l.Logger.Fatal(string(bytes))
+}
+
+// Level returns the echo logging level
+func (l *echoLogger) Level() log.Lvl {
+ return log.Lvl(l.Logger.Level)
+}
+
+// SetLevel sets the echo logging level
+func (l *echoLogger) SetLevel(level log.Lvl) {
+ l.Logger.Level = logrus.Level(level)
+}
+
+// Output returns the echo logging output
+func (l *echoLogger) Output() io.Writer {
+ return l.Writer()
+}
+
+// SetOutput sets the echo logging output
+func (l *echoLogger) SetOutput(output io.Writer) {
+ l.Logger.Logger.Out = output
+}
+
+// Prefix returns the echo logging output
+func (l *echoLogger) Prefix() string {
+ return l.Logger.Data["app"].(string)
+}
+
+// SetPrefix returns the echo logging output
+func (l *echoLogger) SetPrefix(prefix string) {
+ l.Logger.Data["app"] = prefix
+}
+
+func loggerMiddlewareHandler(c echo.Context, next echo.HandlerFunc, log *logger.Logger) error {
+ req := c.Request()
+ res := c.Response()
+ start := time.Now()
+
+ err := next(c)
+ if err != nil {
+ return err
+ }
+ stop := time.Now()
+
+ p := req.URL.Path
+ if p == "" {
+ p = "/"
+ }
+
+ bytesIn := req.Header.Get(echo.HeaderContentLength)
+ if bytesIn == "" {
+ bytesIn = "0"
+ }
+
+ requestID := req.Header.Get(echo.HeaderXRequestID)
+
+ if requestID == "" {
+ requestID = res.Header().Get(echo.HeaderXRequestID)
+ }
+
+ log.WithFields(map[string]interface{}{
+ "id": requestID,
+ "time_rfc3339": time.Now().Format(time.RFC3339),
+ "remote_ip": c.RealIP(),
+ "host": req.Host,
+ "uri": req.RequestURI,
+ "method": req.Method,
+ "path": p,
+ "referer": req.Referer(),
+ "user_agent": req.UserAgent(),
+ "status": res.Status,
+ "latency": strconv.FormatInt(stop.Sub(start).Nanoseconds()/1000, 10),
+ "latency_human": stop.Sub(start).String(),
+ "bytes_in": bytesIn,
+ "bytes_out": strconv.FormatInt(res.Size, 10),
+ "headers": req.Header,
+ "query": req.URL.Query(),
+ }).Info("Handled request")
+
+ return nil
+}
+
+func loggerMiddleware(log *logger.Logger) echo.MiddlewareFunc {
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ return loggerMiddlewareHandler(c, next, log)
+ }
+ }
+}
+
+func setLogMiddleware(e *echo.Echo, log *logger.Logger) {
+ e.Logger = &echoLogger{log}
+ e.Pre(loggerMiddleware(log))
+}
diff --git a/server/serverconfig/ratelimit.go b/server/serverconfig/ratelimit.go
new file mode 100644
index 0000000..fd92a41
--- /dev/null
+++ b/server/serverconfig/ratelimit.go
@@ -0,0 +1,73 @@
+package serverconfig
+
+import (
+ "time"
+
+ "net/http"
+
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+// RateLimitMiddlewareConfig defines the config for RateLimit middleware.
+type RateLimitMiddlewareConfig struct {
+ Skipper middleware.Skipper
+ // Max number of allowed requests on a timeframe
+ MaxRequests int64
+ // The timeframe duration for the requests count
+ BucketDuration time.Duration
+ // Error response message
+ ResponseMessage string
+ // Error response
+ ResponseStatus int
+}
+
+// DefaultRateLimitMiddlewareConfig is the default RateLimit middleware config.
+var DefaultRateLimitMiddlewareConfig = RateLimitMiddlewareConfig{
+ Skipper: middleware.DefaultSkipper,
+ MaxRequests: 10,
+ BucketDuration: time.Second,
+ ResponseMessage: "Too Many Requests",
+ ResponseStatus: http.StatusServiceUnavailable,
+}
+
+// RateLimitMiddleware returns a middleware that protects the API agains massive requests.
+func RateLimitMiddleware() echo.MiddlewareFunc {
+ return RateLimitMiddlewareWithConfig(DefaultRateLimitMiddlewareConfig)
+}
+
+// RateLimitMiddlewareWithConfig returns a RateLimitMiddleware with configuration parameters.
+// See: `RateLimitMiddleware()`.
+func RateLimitMiddlewareWithConfig(config RateLimitMiddlewareConfig) echo.MiddlewareFunc {
+ if config.MaxRequests == 0 {
+ config.MaxRequests = DefaultRateLimitMiddlewareConfig.MaxRequests
+ }
+
+ if config.BucketDuration == 0 {
+ config.BucketDuration = DefaultRateLimitMiddlewareConfig.BucketDuration
+ }
+
+ // limiter := tollbooth.NewLimiterExpiringBuckets(config.MaxRequests, config.BucketDuration, time.Hour, time.Second*0)
+ // limiter.Message = config.ResponseMessage
+ // limiter.StatusCode = config.ResponseStatus
+
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ if config.Skipper(c) {
+ return next(c)
+ }
+
+ // err := tollbooth.LimitByRequest(limiter, c.Request())
+ // if err != nil {
+ // tollbooth.SetResponseHeaders(limiter, c.Response().Writer)
+ // return errors.NewHTTPError(limiter.StatusCode, limiter.Message)
+ // }
+
+ return next(c)
+ }
+ }
+}
+
+func setRateLimitMiddleware(e *echo.Echo) {
+ e.Pre(RateLimitMiddleware())
+}
diff --git a/server/serverconfig/recover.go b/server/serverconfig/recover.go
new file mode 100644
index 0000000..e269493
--- /dev/null
+++ b/server/serverconfig/recover.go
@@ -0,0 +1,10 @@
+package serverconfig
+
+import (
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+func setRecoverMiddleware(e *echo.Echo) {
+ e.Use(middleware.Recover())
+}
diff --git a/server/serverconfig/requestid.go b/server/serverconfig/requestid.go
new file mode 100644
index 0000000..52a4278
--- /dev/null
+++ b/server/serverconfig/requestid.go
@@ -0,0 +1,10 @@
+package serverconfig
+
+import (
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+func setRequestIDMiddleware(e *echo.Echo) {
+ e.Use(middleware.RequestID())
+}
diff --git a/server/serverconfig/route.go b/server/serverconfig/route.go
new file mode 100644
index 0000000..5815523
--- /dev/null
+++ b/server/serverconfig/route.go
@@ -0,0 +1,15 @@
+package serverconfig
+
+import (
+ "net/http"
+
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+func setRouteMiddleware(e *echo.Echo) {
+ middlewareConfig := middleware.DefaultTrailingSlashConfig
+ middlewareConfig.RedirectCode = http.StatusPermanentRedirect
+
+ e.Use(middleware.AddTrailingSlashWithConfig(middlewareConfig))
+}
diff --git a/server/serverconfig/serverconfig.go b/server/serverconfig/serverconfig.go
new file mode 100644
index 0000000..0d3be75
--- /dev/null
+++ b/server/serverconfig/serverconfig.go
@@ -0,0 +1,28 @@
+package serverconfig
+
+import (
+ "bitbucket.org/nemt/nemt-portal-api/domain/service"
+ "bitbucket.org/nemt/nemt-portal-api/infra/config"
+ "bitbucket.org/nemt/nemt-portal-api/infra/errors"
+ "bitbucket.org/nemt/nemt-portal-api/infra/logger"
+ "github.com/labstack/echo"
+)
+
+// SetMiddlewares attaches middlewares to server
+func SetMiddlewares(server *echo.Echo, cfg *config.Config, log *logger.Logger, svc *service.Service) error {
+ setRecoverMiddleware(server)
+ setGZIPMiddleware(server)
+ setRequestIDMiddleware(server)
+ setLogMiddleware(server, log)
+ setCORSMiddleware(server, cfg)
+ setBodyLimitMiddleware(server)
+ setRateLimitMiddleware(server)
+ //setAuthorizationMiddleware(server, log, svc)
+
+ err := setJWTMiddleware(server, cfg)
+ if err != nil {
+ return errors.Wrap(err)
+ }
+
+ return nil
+}
diff --git a/server/serverconfig/util.go b/server/serverconfig/util.go
new file mode 100644
index 0000000..8f57c20
--- /dev/null
+++ b/server/serverconfig/util.go
@@ -0,0 +1,50 @@
+package serverconfig
+
+import (
+ "strings"
+
+ "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
+ "github.com/labstack/echo"
+)
+
+// authSkipper is the default skipper for authentication and authorization
+func authSkipper(ctx echo.Context) bool {
+ path := ctx.Request().URL.Path
+ return (strings.HasPrefix(path, "/health") ||
+ strings.HasPrefix(path, "/v1/authenticate") ||
+ strings.HasPrefix(path, "/v1/docs") ||
+ strings.HasPrefix(path, "/v1/twilio") ||
+ strings.HasPrefix(path, "/v1/twilio/ws") ||
+ strings.Contains(path, "/v1/ext") ||
+ strings.Contains(path, "/v1/notification/ws") ||
+ strings.HasPrefix(path, "/v1/lyfthook") ||
+ strings.HasPrefix(path, "/v1/docs"))
+}
+
+// appSkipper is the default skipper for the application routes
+func appSkipper(ctx echo.Context) bool {
+ path := ctx.Request().URL.Path
+ return strings.HasPrefix(path, "/v1/twilio")
+}
+
+// docsSkipper is the default skipper for documentation
+func docsSkipper(ctx echo.Context) bool {
+ path := ctx.Request().URL.Path
+ return strings.HasPrefix(path, "/v1/docs")
+}
+
+// middlewareErrorWrapper wraps a middleware and applies the default error handling to response
+func middlewareErrorWrapper(middleware echo.MiddlewareFunc) echo.MiddlewareFunc {
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ handlerFunc := middleware(next)
+
+ return func(c echo.Context) error {
+ err := handlerFunc(c)
+ if err != nil {
+ return routeutils.HandleAPIError(c, err)
+ }
+
+ return nil
+ }
+ }
+}
diff --git a/sql/0000-initial-db-structure.sql b/sql/0000-initial-db-structure.sql
new file mode 100644
index 0000000..acc4f83
--- /dev/null
+++ b/sql/0000-initial-db-structure.sql
@@ -0,0 +1,72 @@
+SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
+SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
+SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
+
+-- -----------------------------------------------------
+-- Schema db_boilerplate
+-- -----------------------------------------------------
+
+-- -----------------------------------------------------
+-- Schema db_boilerplate
+-- -----------------------------------------------------
+CREATE SCHEMA IF NOT EXISTS `db_boilerplate` DEFAULT CHARACTER SET latin1 ;
+USE `db_boilerplate` ;
+
+
+-- -----------------------------------------------------
+-- Table `db_boilerplate`.`tab_civil_status`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `db_boilerplate`.`tab_civil_status` (
+ `civil_status_id` INT NOT NULL AUTO_INCREMENT,
+ `civil_status_name` VARCHAR(30) NOT NULL,
+ `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `active` TINYINT(1) NOT NULL DEFAULT 1,
+ PRIMARY KEY (`civil_status_id`),
+ UNIQUE INDEX `name_UNIQUE` (`civil_status_name` ASC))
+ENGINE = InnoDB;
+
+
+
+-- -----------------------------------------------------
+-- Table `db_boilerplate`.`tab_state`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `db_boilerplate`.`tab_state` (
+ `state_id` INT NOT NULL AUTO_INCREMENT,
+ `state_name` VARCHAR(20) NOT NULL,
+ `acronym` VARCHAR(2) NOT NULL,
+ `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `active` TINYINT(1) NOT NULL DEFAULT 1,
+ PRIMARY KEY (`state_id`),
+ UNIQUE INDEX `acronym_UNIQUE` (`acronym` ASC))
+ENGINE = InnoDB;
+
+
+
+-- -----------------------------------------------------
+-- Table `db_boilerplate`.`tab_city`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `db_boilerplate`.`tab_city` (
+ `city_id` INT NOT NULL AUTO_INCREMENT,
+ `city_name` VARCHAR(250) NOT NULL,
+ `state_id` INT NOT NULL,
+ `ibge_code` VARCHAR(8) NOT NULL,
+ `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `active` TINYINT(1) NOT NULL DEFAULT 1,
+ PRIMARY KEY (`city_id`),
+ INDEX `fk_tab_city_tab_state1_idx` (`state_id` ASC),
+ UNIQUE INDEX `name_state_UNIQUE` (`city_name` ASC, `state_id` ASC),
+ CONSTRAINT `fk_tab_city_tab_state1`
+ FOREIGN KEY (`state_id`)
+ REFERENCES `db_boilerplate`.`tab_state` (`state_id`)
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+
+SET SQL_MODE=@OLD_SQL_MODE;
+SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
+SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
diff --git a/sql/0001-initial-db-load.sql b/sql/0001-initial-db-load.sql
new file mode 100644
index 0000000..4870429
--- /dev/null
+++ b/sql/0001-initial-db-load.sql
@@ -0,0 +1,5607 @@
+INSERT INTO `tab_civil_status` (`civil_status_id`, `civil_status_name`, `active`) VALUES
+ (1, 'Solteiro', 1),
+ (2, 'Casado', 1),
+ (3, 'Viúvo', 1),
+ (4, 'Desquitado/Separado', 1),
+ (5, 'Divorciado', 1),
+ (6, 'Outros', 1);
+
+
+INSERT INTO `tab_state`(`state_id`, `acronym`, `state_name`, `active`) VALUES
+ (1,'AC', 'Acre', 1),
+ (2,'AL', 'Alagoas', 1),
+ (3,'AM', 'Amazonas', 1),
+ (4,'AP', 'Amapá', 1),
+ (5,'BA', 'Bahia', 1),
+ (6,'CE', 'Ceará', 1),
+ (7,'DF', 'Distrito Federal', 1),
+ (8,'ES', 'Espírito Santo', 1),
+ (9,'GO', 'Goiás', 1),
+ (10,'MA', 'Maranhão', 1),
+ (11,'MG', 'Minas Gerais', 1),
+ (12,'MS', 'Mato Grosso do Sul', 1),
+ (13,'MT', 'Mato Grosso', 1),
+ (14,'PA', 'Pará', 1),
+ (15,'PB', 'Paraíba', 1),
+ (16,'PE', 'Pernanbuco', 1),
+ (17,'PI', 'Piauí', 1),
+ (18,'PR', 'Paraná', 1),
+ (19,'RJ', 'Rio de Janeiro', 1),
+ (20,'RN', 'Rio Grande do Norte', 1),
+ (21,'RO', 'Rondônia', 1),
+ (22,'RR', 'Roraima', 1),
+ (23,'RS', 'Rio Grande do Sul', 1),
+ (24,'SC', 'Santa Catarina', 1),
+ (25,'SE', 'Sergipe', 1),
+ (26,'SP', 'São Paulo', 1),
+ (27,'TO', 'Tocantins', 1);
+
+/*!40000 ALTER TABLE `tab_city` DISABLE KEYS */;
+INSERT INTO `tab_city` (`city_id`, `city_name`, `state_id`, `ibge_code`, `active`) VALUES
+ (1, 'ACRELANDIA', 1, '1200013', 1),
+ (2, 'ASSIS BRASIL', 1, '1200054', 1),
+ (3, 'BRASILEIA', 1, '1200104', 1),
+ (4, 'BUJARI', 1, '1200138', 1),
+ (5, 'CAPIXABA', 1, '1200179', 1),
+ (6, 'CRUZEIRO DO SUL', 1, '1200203', 1),
+ (7, 'EPITACIOLANDIA', 1, '1200252', 1),
+ (8, 'FEIJO', 1, '1200302', 1),
+ (9, 'JORDAO', 1, '1200328', 1),
+ (10, 'MANCIO LIMA', 1, '1200336', 1),
+ (11, 'MANOEL URBANO', 1, '1200344', 1),
+ (12, 'MARECHAL THAUMATURGO', 1, '1200351', 1),
+ (13, 'PLACIDO DE CASTRO', 1, '1200385', 1),
+ (14, 'PORTO WALTER', 1, '1200393', 1),
+ (15, 'RIO BRANCO', 1, '1200401', 1),
+ (16, 'RODRIGUES ALVES', 1, '1200427', 1),
+ (17, 'SANTA ROSA DO PURUS', 1, '1200435', 1),
+ (18, 'SENADOR GUIOMARD', 1, '1200450', 1),
+ (19, 'SENA MADUREIRA', 1, '1200500', 1),
+ (20, 'TARAUACA', 1, '1200609', 1),
+ (21, 'XAPURI', 1, '1200708', 1),
+ (22, 'PORTO ACRE', 1, '1200807', 1),
+ (23, 'AGUA BRANCA', 2, '2700102', 1),
+ (24, 'ANADIA', 2, '2700201', 1),
+ (25, 'ARAPIRACA', 2, '2700300', 1),
+ (26, 'ATALAIA', 2, '2700409', 1),
+ (27, 'BARRA DE SANTO ANTONIO', 2, '2700508', 1),
+ (28, 'BARRA DE SAO MIGUEL', 2, '2700607', 1),
+ (29, 'BATALHA', 2, '2700706', 1),
+ (30, 'BELEM', 2, '2700805', 1),
+ (31, 'BELO MONTE', 2, '2700904', 1),
+ (32, 'BOCA DA MATA', 2, '2701001', 1),
+ (33, 'BRANQUINHA', 2, '2701100', 1),
+ (34, 'CACIMBINHAS', 2, '2701209', 1),
+ (35, 'CAJUEIRO', 2, '2701308', 1),
+ (36, 'CAMPESTRE', 2, '2701357', 1),
+ (37, 'CAMPO ALEGRE', 2, '2701407', 1),
+ (38, 'CAMPO GRANDE', 2, '2701506', 1),
+ (39, 'CANAPI', 2, '2701605', 1),
+ (40, 'CAPELA', 2, '2701704', 1),
+ (41, 'CARNEIROS', 2, '2701803', 1),
+ (42, 'CHA PRETA', 2, '2701902', 1),
+ (43, 'COITE DO NOIA', 2, '2702009', 1),
+ (44, 'COLONIA LEOPOLDINA', 2, '2702108', 1),
+ (45, 'COQUEIRO SECO', 2, '2702207', 1),
+ (46, 'CORURIPE', 2, '2702306', 1),
+ (47, 'CRAIBAS', 2, '2702355', 1),
+ (48, 'DELMIRO GOUVEIA', 2, '2702405', 1),
+ (49, 'DOIS RIACHOS', 2, '2702504', 1),
+ (50, 'ESTRELA DE ALAGOAS', 2, '2702553', 1),
+ (51, 'FEIRA GRANDE', 2, '2702603', 1),
+ (52, 'FELIZ DESERTO', 2, '2702702', 1),
+ (53, 'FLEXEIRAS', 2, '2702801', 1),
+ (54, 'GIRAU DO PONCIANO', 2, '2702900', 1),
+ (55, 'IBATEGUARA', 2, '2703007', 1),
+ (56, 'IGACI', 2, '2703106', 1),
+ (57, 'IGREJA NOVA', 2, '2703205', 1),
+ (58, 'INHAPI', 2, '2703304', 1),
+ (59, 'JACARE DOS HOMENS', 2, '2703403', 1),
+ (60, 'JACUIPE', 2, '2703502', 1),
+ (61, 'JAPARATINGA', 2, '2703601', 1),
+ (62, 'JARAMATAIA', 2, '2703700', 1),
+ (63, 'JEQUIA DA PRAIA', 2, '2703759', 1),
+ (64, 'JOAQUIM GOMES', 2, '2703809', 1),
+ (65, 'JUNDIA', 2, '2703908', 1),
+ (66, 'JUNQUEIRO', 2, '2704005', 1),
+ (67, 'LAGOA DA CANOA', 2, '2704104', 1),
+ (68, 'LIMOEIRO DE ANADIA', 2, '2704203', 1),
+ (69, 'MACEIO', 2, '2704302', 1),
+ (70, 'MAJOR ISIDORO', 2, '2704401', 1),
+ (71, 'MARAGOGI', 2, '2704500', 1),
+ (72, 'MARAVILHA', 2, '2704609', 1),
+ (73, 'MARECHAL DEODORO', 2, '2704708', 1),
+ (74, 'MARIBONDO', 2, '2704807', 1),
+ (75, 'MAR VERMELHO', 2, '2704906', 1),
+ (76, 'MATA GRANDE', 2, '2705002', 1),
+ (77, 'MATRIZ DE CAMARAGIBE', 2, '2705101', 1),
+ (78, 'MESSIAS', 2, '2705200', 1),
+ (79, 'MINADOR DO NEGRAO', 2, '2705309', 1),
+ (80, 'MONTEIROPOLIS', 2, '2705408', 1),
+ (81, 'MURICI', 2, '2705507', 1),
+ (82, 'NOVO LINO', 2, '2705606', 1),
+ (83, 'OLHO DAGUA DAS FLORES', 2, '2705705', 1),
+ (84, 'OLHO DAGUA DO CASADO', 2, '2705804', 1),
+ (85, 'OLHO DAGUA GRANDE', 2, '2705903', 1),
+ (86, 'OLIVENCA', 2, '2706000', 1),
+ (87, 'OURO BRANCO', 2, '2706109', 1),
+ (88, 'PALESTINA', 2, '2706208', 1),
+ (89, 'PALMEIRA DOS INDIOS', 2, '2706307', 1),
+ (90, 'PAO DE ACUCAR', 2, '2706406', 1),
+ (91, 'PARICONHA', 2, '2706422', 1),
+ (92, 'PARIPUEIRA', 2, '2706448', 1),
+ (93, 'PASSO DE CAMARAGIBE', 2, '2706505', 1),
+ (94, 'PAULO JACINTO', 2, '2706604', 1),
+ (95, 'PENEDO', 2, '2706703', 1),
+ (96, 'PIACABUCU', 2, '2706802', 1),
+ (97, 'PILAR', 2, '2706901', 1),
+ (98, 'PINDOBA', 2, '2707008', 1),
+ (99, 'PIRANHAS', 2, '2707107', 1),
+ (100, 'POCO DAS TRINCHEIRAS', 2, '2707206', 1),
+ (101, 'PORTO CALVO', 2, '2707305', 1),
+ (102, 'PORTO DE PEDRAS', 2, '2707404', 1),
+ (103, 'PORTO REAL DO COLEGIO', 2, '2707503', 1),
+ (104, 'QUEBRANGULO', 2, '2707602', 1),
+ (105, 'RIO LARGO', 2, '2707701', 1),
+ (106, 'ROTEIRO', 2, '2707800', 1),
+ (107, 'SANTA LUZIA DO NORTE', 2, '2707909', 1),
+ (108, 'SANTANA DO IPANEMA', 2, '2708006', 1),
+ (109, 'SANTANA DO MUNDAU', 2, '2708105', 1),
+ (110, 'SAO BRAS', 2, '2708204', 1),
+ (111, 'SAO JOSE DA LAJE', 2, '2708303', 1),
+ (112, 'SAO JOSE DA TAPERA', 2, '2708402', 1),
+ (113, 'SAO LUIS DO QUITUNDE', 2, '2708501', 1),
+ (114, 'SAO MIGUEL DOS CAMPOS', 2, '2708600', 1),
+ (115, 'SAO MIGUEL DOS MILAGRES', 2, '2708709', 1),
+ (116, 'SAO SEBASTIAO', 2, '2708808', 1),
+ (117, 'SATUBA', 2, '2708907', 1),
+ (118, 'SENADOR RUI PALMEIRA', 2, '2708956', 1),
+ (119, 'TANQUE DARCA', 2, '2709004', 1),
+ (120, 'TAQUARANA', 2, '2709103', 1),
+ (121, 'TEOTONIO VILELA', 2, '2709152', 1),
+ (122, 'TRAIPU', 2, '2709202', 1),
+ (123, 'UNIAO DOS PALMARES', 2, '2709301', 1),
+ (124, 'VICOSA', 2, '2709400', 1),
+ (125, 'ALVARAES', 3, '1300029', 1),
+ (126, 'AMATURA', 3, '1300060', 1),
+ (127, 'ANAMA', 3, '1300086', 1),
+ (128, 'ANORI', 3, '1300102', 1),
+ (129, 'APUI', 3, '1300144', 1),
+ (130, 'ATALAIA DO NORTE', 3, '1300201', 1),
+ (131, 'AUTAZES', 3, '1300300', 1),
+ (132, 'BARCELOS', 3, '1300409', 1),
+ (133, 'BARREIRINHA', 3, '1300508', 1),
+ (134, 'BENJAMIN CONSTANT', 3, '1300607', 1),
+ (135, 'BERURI', 3, '1300631', 1),
+ (136, 'BOA VISTA DO RAMOS', 3, '1300680', 1),
+ (137, 'BOCA DO ACRE', 3, '1300706', 1),
+ (138, 'BORBA', 3, '1300805', 1),
+ (139, 'CAAPIRANGA', 3, '1300839', 1),
+ (140, 'CANUTAMA', 3, '1300904', 1),
+ (141, 'CARAUARI', 3, '1301001', 1),
+ (142, 'CAREIRO', 3, '1301100', 1),
+ (143, 'CAREIRO DA VARZEA', 3, '1301159', 1),
+ (144, 'COARI', 3, '1301209', 1),
+ (145, 'CODAJAS', 3, '1301308', 1),
+ (146, 'EIRUNEPE', 3, '1301407', 1),
+ (147, 'ENVIRA', 3, '1301506', 1),
+ (148, 'FONTE BOA', 3, '1301605', 1),
+ (149, 'GUAJARA', 3, '1301654', 1),
+ (150, 'HUMAITA', 3, '1301704', 1),
+ (151, 'IPIXUNA', 3, '1301803', 1),
+ (152, 'IRANDUBA', 3, '1301852', 1),
+ (153, 'ITACOATIARA', 3, '1301902', 1),
+ (154, 'ITAMARATI', 3, '1301951', 1),
+ (155, 'ITAPIRANGA', 3, '1302009', 1),
+ (156, 'JAPURA', 3, '1302108', 1),
+ (157, 'JURUA', 3, '1302207', 1),
+ (158, 'JUTAI', 3, '1302306', 1),
+ (159, 'LABREA', 3, '1302405', 1),
+ (160, 'MANACAPURU', 3, '1302504', 1),
+ (161, 'MANAQUIRI', 3, '1302553', 1),
+ (162, 'MANAUS', 3, '1302603', 1),
+ (163, 'MANICORE', 3, '1302702', 1),
+ (164, 'MARAA', 3, '1302801', 1),
+ (165, 'MAUES', 3, '1302900', 1),
+ (166, 'NHAMUNDA', 3, '1303007', 1),
+ (167, 'NOVA OLINDA DO NORTE', 3, '1303106', 1),
+ (168, 'NOVO AIRAO', 3, '1303205', 1),
+ (169, 'NOVO ARIPUANA', 3, '1303304', 1),
+ (170, 'PARINTINS', 3, '1303403', 1),
+ (171, 'PAUINI', 3, '1303502', 1),
+ (172, 'PRESIDENTE FIGUEIREDO', 3, '1303536', 1),
+ (173, 'RIO PRETO DA EVA', 3, '1303569', 1),
+ (174, 'SANTA ISABEL DO RIO NEGRO', 3, '1303601', 1),
+ (175, 'SANTO ANTONIO DO ICA', 3, '1303700', 1),
+ (176, 'SAO GABRIEL DA CACHOEIRA', 3, '1303809', 1),
+ (177, 'SAO PAULO DE OLIVENCA', 3, '1303908', 1),
+ (178, 'SAO SEBASTIAO DO UATUMA', 3, '1303957', 1),
+ (179, 'SILVES', 3, '1304005', 1),
+ (180, 'TABATINGA', 3, '1304062', 1),
+ (181, 'TAPAUA', 3, '1304104', 1),
+ (182, 'TEFE', 3, '1304203', 1),
+ (183, 'TONANTINS', 3, '1304237', 1),
+ (184, 'UARINI', 3, '1304260', 1),
+ (185, 'URUCARA', 3, '1304302', 1),
+ (186, 'URUCURITUBA', 3, '1304401', 1),
+ (187, 'SERRA DO NAVIO', 4, '1600055', 1),
+ (188, 'AMAPA', 4, '1600105', 1),
+ (189, 'PEDRA BRANCA DO AMAPARI', 4, '1600154', 1),
+ (190, 'CALCOENE', 4, '1600204', 1),
+ (191, 'CUTIAS', 4, '1600212', 1),
+ (192, 'FERREIRA GOMES', 4, '1600238', 1),
+ (193, 'BOILERPLATEBAL', 4, '1600253', 1),
+ (194, 'LARANJAL DO JARI', 4, '1600279', 1),
+ (195, 'MACAPA', 4, '1600303', 1),
+ (196, 'MAZAGAO', 4, '1600402', 1),
+ (197, 'OIAPOQUE', 4, '1600501', 1),
+ (198, 'PORTO GRANDE', 4, '1600535', 1),
+ (199, 'PRACUUBA', 4, '1600550', 1),
+ (200, 'SANTANA', 4, '1600600', 1),
+ (201, 'TARTARUGALZINHO', 4, '1600709', 1),
+ (202, 'VITORIA DO JARI', 4, '1600808', 1),
+ (203, 'ABAIRA', 5, '2900108', 1),
+ (204, 'ABARE', 5, '2900207', 1),
+ (205, 'ACAJUTIBA', 5, '2900306', 1),
+ (206, 'ADUSTINA', 5, '2900355', 1),
+ (207, 'AGUA FRIA', 5, '2900405', 1),
+ (208, 'ERICO CARDOSO', 5, '2900504', 1),
+ (209, 'AIQUARA', 5, '2900603', 1),
+ (210, 'ALAGOINHAS', 5, '2900702', 1),
+ (211, 'ALCOBACA', 5, '2900801', 1),
+ (212, 'ALMADINA', 5, '2900900', 1),
+ (213, 'AMARGOSA', 5, '2901007', 1),
+ (214, 'AMELIA RODRIGUES', 5, '2901106', 1),
+ (215, 'AMERICA DOURADA', 5, '2901155', 1),
+ (216, 'ANAGE', 5, '2901205', 1),
+ (217, 'ANDARAI', 5, '2901304', 1),
+ (218, 'ANDORINHA', 5, '2901353', 1),
+ (219, 'ANGICAL', 5, '2901403', 1),
+ (220, 'ANGUERA', 5, '2901502', 1),
+ (221, 'ANTAS', 5, '2901601', 1),
+ (222, 'ANTONIO CARDOSO', 5, '2901700', 1),
+ (223, 'ANTONIO GONCALVES', 5, '2901809', 1),
+ (224, 'APORA', 5, '2901908', 1),
+ (225, 'APUAREMA', 5, '2901957', 1),
+ (226, 'ARACATU', 5, '2902005', 1),
+ (227, 'ARACAS', 5, '2902054', 1),
+ (228, 'ARACI', 5, '2902104', 1),
+ (229, 'ARAMARI', 5, '2902203', 1),
+ (230, 'ARATACA', 5, '2902252', 1),
+ (231, 'ARATUIPE', 5, '2902302', 1),
+ (232, 'AURELINO LEAL', 5, '2902401', 1),
+ (233, 'BAIANOPOLIS', 5, '2902500', 1),
+ (234, 'BAIXA GRANDE', 5, '2902609', 1),
+ (235, 'BANZAE', 5, '2902658', 1),
+ (236, 'BARRA', 5, '2902708', 1),
+ (237, 'BARRA DA ESTIVA', 5, '2902807', 1),
+ (238, 'BARRA DO CHOCA', 5, '2902906', 1),
+ (239, 'BARRA DO MENDES', 5, '2903003', 1),
+ (240, 'BARRA DO ROCHA', 5, '2903102', 1),
+ (241, 'BARREIRAS', 5, '2903201', 1),
+ (242, 'BARRO ALTO', 5, '2903235', 1),
+ (243, 'BARROCAS', 5, '2903276', 1),
+ (244, 'BARRO PRETO', 5, '2903300', 1),
+ (245, 'BELMONTE', 5, '2903409', 1),
+ (246, 'BELO CAMPO', 5, '2903508', 1),
+ (247, 'BIRITINGA', 5, '2903607', 1),
+ (248, 'BOA NOVA', 5, '2903706', 1),
+ (249, 'BOA VISTA DO TUPIM', 5, '2903805', 1),
+ (250, 'BOM JESUS DA LAPA', 5, '2903904', 1),
+ (251, 'BOM JESUS DA SERRA', 5, '2903953', 1),
+ (252, 'BONINAL', 5, '2904001', 1),
+ (253, 'BONITO', 5, '2904050', 1),
+ (254, 'BOQUIRA', 5, '2904100', 1),
+ (255, 'BOTUPORA', 5, '2904209', 1),
+ (256, 'BREJOES', 5, '2904308', 1),
+ (257, 'BREJOLANDIA', 5, '2904407', 1),
+ (258, 'BROTAS DE MACAUBAS', 5, '2904506', 1),
+ (259, 'BRUMADO', 5, '2904605', 1),
+ (260, 'BUERAREMA', 5, '2904704', 1),
+ (261, 'BURITIRAMA', 5, '2904753', 1),
+ (262, 'CAATIBA', 5, '2904803', 1),
+ (263, 'CABACEIRAS DO PARAGUACU', 5, '2904852', 1),
+ (264, 'CACHOEIRA', 5, '2904902', 1),
+ (265, 'CACULE', 5, '2905008', 1),
+ (266, 'CAEM', 5, '2905107', 1),
+ (267, 'CAETANOS', 5, '2905156', 1),
+ (268, 'CAETITE', 5, '2905206', 1),
+ (269, 'CAFARNAUM', 5, '2905305', 1),
+ (270, 'CAIRU', 5, '2905404', 1),
+ (271, 'CALDEIRAO GRANDE', 5, '2905503', 1),
+ (272, 'CAMACAN', 5, '2905602', 1),
+ (273, 'CAMACARI', 5, '2905701', 1),
+ (274, 'CAMAMU', 5, '2905800', 1),
+ (275, 'CAMPO ALEGRE DE LOURDES', 5, '2905909', 1),
+ (276, 'CAMPO FORMOSO', 5, '2906006', 1),
+ (277, 'CANAPOLIS', 5, '2906105', 1),
+ (278, 'CANARANA', 5, '2906204', 1),
+ (279, 'CANAVIEIRAS', 5, '2906303', 1),
+ (280, 'CANDEAL', 5, '2906402', 1),
+ (281, 'CANDEIAS', 5, '2906501', 1),
+ (282, 'CANDIBA', 5, '2906600', 1),
+ (283, 'CANDIDO SALES', 5, '2906709', 1),
+ (284, 'CANSANCAO', 5, '2906808', 1),
+ (285, 'CANUDOS', 5, '2906824', 1),
+ (286, 'CAPELA DO ALTO ALEGRE', 5, '2906857', 1),
+ (287, 'CAPIM GROSSO', 5, '2906873', 1),
+ (288, 'CARAIBAS', 5, '2906899', 1),
+ (289, 'CARAVELAS', 5, '2906907', 1),
+ (290, 'CARDEAL DA SILVA', 5, '2907004', 1),
+ (291, 'CARINHANHA', 5, '2907103', 1),
+ (292, 'CASA NOVA', 5, '2907202', 1),
+ (293, 'CASTRO ALVES', 5, '2907301', 1),
+ (294, 'CATOLANDIA', 5, '2907400', 1),
+ (295, 'CATU', 5, '2907509', 1),
+ (296, 'CATURAMA', 5, '2907558', 1),
+ (297, 'CENTRAL', 5, '2907608', 1),
+ (298, 'CHORROCHO', 5, '2907707', 1),
+ (299, 'CICERO DANTAS', 5, '2907806', 1),
+ (300, 'CIPO', 5, '2907905', 1),
+ (301, 'COARACI', 5, '2908002', 1),
+ (302, 'COCOS', 5, '2908101', 1),
+ (303, 'CONCEICAO DA FEIRA', 5, '2908200', 1),
+ (304, 'CONCEICAO DO ALMEIDA', 5, '2908309', 1),
+ (305, 'CONCEICAO DO COITE', 5, '2908408', 1),
+ (306, 'CONCEICAO DO JACUIPE', 5, '2908507', 1),
+ (307, 'CONDE', 5, '2908606', 1),
+ (308, 'CONDEUBA', 5, '2908705', 1),
+ (309, 'CONTENDAS DO SINCORA', 5, '2908804', 1),
+ (310, 'CORACAO DE MARIA', 5, '2908903', 1),
+ (311, 'CORDEIROS', 5, '2909000', 1),
+ (312, 'CORIBE', 5, '2909109', 1),
+ (313, 'CORONEL JOAO SA', 5, '2909208', 1),
+ (314, 'CORRENTINA', 5, '2909307', 1),
+ (315, 'COTEGIPE', 5, '2909406', 1),
+ (316, 'CRAVOLANDIA', 5, '2909505', 1),
+ (317, 'CRISOPOLIS', 5, '2909604', 1),
+ (318, 'CRISTOPOLIS', 5, '2909703', 1),
+ (319, 'CRUZ DAS ALMAS', 5, '2909802', 1),
+ (320, 'CURACA', 5, '2909901', 1),
+ (321, 'DARIO MEIRA', 5, '2910008', 1),
+ (322, 'DIAS DAVILA', 5, '2910057', 1),
+ (323, 'DOM BASILIO', 5, '2910107', 1),
+ (324, 'DOM MACEDO COSTA', 5, '2910206', 1),
+ (325, 'ELISIO MEDRADO', 5, '2910305', 1),
+ (326, 'ENCRUZILHADA', 5, '2910404', 1),
+ (327, 'ENTRE RIOS', 5, '2910503', 1),
+ (328, 'ESPLANADA', 5, '2910602', 1),
+ (329, 'EUCLIDES DA CUNHA', 5, '2910701', 1),
+ (330, 'EUNAPOLIS', 5, '2910727', 1),
+ (331, 'FATIMA', 5, '2910750', 1),
+ (332, 'FEIRA DA MATA', 5, '2910776', 1),
+ (333, 'FEIRA DE SANTANA', 5, '2910800', 1),
+ (334, 'FILADELFIA', 5, '2910859', 1),
+ (335, 'FIRMINO ALVES', 5, '2910909', 1),
+ (336, 'FLORESTA AZUL', 5, '2911006', 1),
+ (337, 'FORMOSA DO RIO PRETO', 5, '2911105', 1),
+ (338, 'GANDU', 5, '2911204', 1),
+ (339, 'GAVIAO', 5, '2911253', 1),
+ (340, 'GENTIO DO OURO', 5, '2911303', 1),
+ (341, 'GLORIA', 5, '2911402', 1),
+ (342, 'GONGOGI', 5, '2911501', 1),
+ (343, 'GOVERNADOR MANGABEIRA', 5, '2911600', 1),
+ (344, 'GUAJERU', 5, '2911659', 1),
+ (345, 'GUANAMBI', 5, '2911709', 1),
+ (346, 'GUARATINGA', 5, '2911808', 1),
+ (347, 'HELIOPOLIS', 5, '2911857', 1),
+ (348, 'IACU', 5, '2911907', 1),
+ (349, 'IBIASSUCE', 5, '2912004', 1),
+ (350, 'IBICARAI', 5, '2912103', 1),
+ (351, 'IBICOARA', 5, '2912202', 1),
+ (352, 'IBICUI', 5, '2912301', 1),
+ (353, 'IBIPEBA', 5, '2912400', 1),
+ (354, 'IBIPITANGA', 5, '2912509', 1),
+ (355, 'IBIQUERA', 5, '2912608', 1),
+ (356, 'IBIRAPITANGA', 5, '2912707', 1),
+ (357, 'IBIRAPUA', 5, '2912806', 1),
+ (358, 'IBIRATAIA', 5, '2912905', 1),
+ (359, 'IBITIARA', 5, '2913002', 1),
+ (360, 'IBITITA', 5, '2913101', 1),
+ (361, 'IBOTIRAMA', 5, '2913200', 1),
+ (362, 'ICHU', 5, '2913309', 1),
+ (363, 'IGAPORA', 5, '2913408', 1),
+ (364, 'IGRAPIUNA', 5, '2913457', 1),
+ (365, 'IGUAI', 5, '2913507', 1),
+ (366, 'ILHEUS', 5, '2913606', 1),
+ (367, 'INHAMBUPE', 5, '2913705', 1),
+ (368, 'IPECAETA', 5, '2913804', 1),
+ (369, 'IPIAU', 5, '2913903', 1),
+ (370, 'IPIRA', 5, '2914000', 1),
+ (371, 'IPUPIARA', 5, '2914109', 1),
+ (372, 'IRAJUBA', 5, '2914208', 1),
+ (373, 'IRAMAIA', 5, '2914307', 1),
+ (374, 'IRAQUARA', 5, '2914406', 1),
+ (375, 'IRARA', 5, '2914505', 1),
+ (376, 'IRECE', 5, '2914604', 1),
+ (377, 'ITABELA', 5, '2914653', 1),
+ (378, 'ITABERABA', 5, '2914703', 1),
+ (379, 'ITABUNA', 5, '2914802', 1),
+ (380, 'ITACARE', 5, '2914901', 1),
+ (381, 'ITAETE', 5, '2915007', 1),
+ (382, 'ITAGI', 5, '2915106', 1),
+ (383, 'ITAGIBA', 5, '2915205', 1),
+ (384, 'ITAGIMIRIM', 5, '2915304', 1),
+ (385, 'ITAGUACU DA BAHIA', 5, '2915353', 1),
+ (386, 'ITAJU DO COLONIA', 5, '2915403', 1),
+ (387, 'ITAJUIPE', 5, '2915502', 1),
+ (388, 'ITAMARAJU', 5, '2915601', 1),
+ (389, 'ITAMARI', 5, '2915700', 1),
+ (390, 'ITAMBE', 5, '2915809', 1),
+ (391, 'ITANAGRA', 5, '2915908', 1),
+ (392, 'ITANHEM', 5, '2916005', 1),
+ (393, 'ITAPARICA', 5, '2916104', 1),
+ (394, 'ITAPE', 5, '2916203', 1),
+ (395, 'ITAPEBI', 5, '2916302', 1),
+ (396, 'ITAPETINGA', 5, '2916401', 1),
+ (397, 'ITAPICURU', 5, '2916500', 1),
+ (398, 'ITAPITANGA', 5, '2916609', 1),
+ (399, 'ITAQUARA', 5, '2916708', 1),
+ (400, 'ITARANTIM', 5, '2916807', 1),
+ (401, 'ITATIM', 5, '2916856', 1),
+ (402, 'ITIRUCU', 5, '2916906', 1),
+ (403, 'ITIUBA', 5, '2917003', 1),
+ (404, 'ITORORO', 5, '2917102', 1),
+ (405, 'ITUACU', 5, '2917201', 1),
+ (406, 'ITUBERA', 5, '2917300', 1),
+ (407, 'IUIU', 5, '2917334', 1),
+ (408, 'JABORANDI', 5, '2917359', 1),
+ (409, 'JACARACI', 5, '2917409', 1),
+ (410, 'JACOBINA', 5, '2917508', 1),
+ (411, 'JAGUAQUARA', 5, '2917607', 1),
+ (412, 'JAGUARARI', 5, '2917706', 1),
+ (413, 'JAGUARIPE', 5, '2917805', 1),
+ (414, 'JANDAIRA', 5, '2917904', 1),
+ (415, 'JEQUIE', 5, '2918001', 1),
+ (416, 'JEREMOABO', 5, '2918100', 1),
+ (417, 'JIQUIRICA', 5, '2918209', 1),
+ (418, 'JBOILERPLATENA', 5, '2918308', 1),
+ (419, 'JOAO DOURADO', 5, '2918357', 1),
+ (420, 'JUAZEIRO', 5, '2918407', 1),
+ (421, 'JUCURUCU', 5, '2918456', 1),
+ (422, 'JUSSARA', 5, '2918506', 1),
+ (423, 'JUSSARI', 5, '2918555', 1),
+ (424, 'JUSSIAPE', 5, '2918605', 1),
+ (425, 'LAFAIETE COUTINHO', 5, '2918704', 1),
+ (426, 'LAGOA REAL', 5, '2918753', 1),
+ (427, 'LAJE', 5, '2918803', 1),
+ (428, 'LAJEDAO', 5, '2918902', 1),
+ (429, 'LAJEDINHO', 5, '2919009', 1),
+ (430, 'LAJEDO DO TABOCAL', 5, '2919058', 1),
+ (431, 'LAMARAO', 5, '2919108', 1),
+ (432, 'LAPAO', 5, '2919157', 1),
+ (433, 'LAURO DE FREITAS', 5, '2919207', 1),
+ (434, 'LENCOIS', 5, '2919306', 1),
+ (435, 'LICINIO DE ALMEIDA', 5, '2919405', 1),
+ (436, 'LIVRAMENTO DE NOSSA SENHORA', 5, '2919504', 1),
+ (437, 'LUIS EDUARDO MAGALHAES', 5, '2919553', 1),
+ (438, 'MACAJUBA', 5, '2919603', 1),
+ (439, 'MACARANI', 5, '2919702', 1),
+ (440, 'MACAUBAS', 5, '2919801', 1),
+ (441, 'MACURURE', 5, '2919900', 1),
+ (442, 'MADRE DE DEUS', 5, '2919926', 1),
+ (443, 'MAETINGA', 5, '2919959', 1),
+ (444, 'MAIQUINIQUE', 5, '2920007', 1),
+ (445, 'MAIRI', 5, '2920106', 1),
+ (446, 'MALHADA', 5, '2920205', 1),
+ (447, 'MALHADA DE PEDRAS', 5, '2920304', 1),
+ (448, 'MANOEL VITORINO', 5, '2920403', 1),
+ (449, 'MANSIDAO', 5, '2920452', 1),
+ (450, 'MARACAS', 5, '2920502', 1),
+ (451, 'MARAGOGIPE', 5, '2920601', 1),
+ (452, 'MARAU', 5, '2920700', 1),
+ (453, 'MARCIONILIO SOUZA', 5, '2920809', 1),
+ (454, 'MASCOTE', 5, '2920908', 1),
+ (455, 'MATA DE SAO JOAO', 5, '2921005', 1),
+ (456, 'MATINA', 5, '2921054', 1),
+ (457, 'MEDEIROS NETO', 5, '2921104', 1),
+ (458, 'MIGUEL CALMON', 5, '2921203', 1),
+ (459, 'MILAGRES', 5, '2921302', 1),
+ (460, 'MIRANGABA', 5, '2921401', 1),
+ (461, 'MIRANTE', 5, '2921450', 1),
+ (462, 'MONTE SANTO', 5, '2921500', 1),
+ (463, 'MORPARA', 5, '2921609', 1),
+ (464, 'MORRO DO CHAPEU', 5, '2921708', 1),
+ (465, 'MORTUGABA', 5, '2921807', 1),
+ (466, 'MUCUGE', 5, '2921906', 1),
+ (467, 'MUCURI', 5, '2922003', 1),
+ (468, 'MULUNGU DO MORRO', 5, '2922052', 1),
+ (469, 'MUNDO NOVO', 5, '2922102', 1),
+ (470, 'MUNIZ FERREIRA', 5, '2922201', 1),
+ (471, 'MUQUEM DE SAO FRANCISCO', 5, '2922250', 1),
+ (472, 'MURITIBA', 5, '2922300', 1),
+ (473, 'MUTUIPE', 5, '2922409', 1),
+ (474, 'NAZARE', 5, '2922508', 1),
+ (475, 'NILO PECANHA', 5, '2922607', 1),
+ (476, 'NORDESTINA', 5, '2922656', 1),
+ (477, 'NOVA CANAA', 5, '2922706', 1),
+ (478, 'NOVA FATIMA', 5, '2922730', 1),
+ (479, 'NOVA IBIA', 5, '2922755', 1),
+ (480, 'NOVA ITARANA', 5, '2922805', 1),
+ (481, 'NOVA REDENCAO', 5, '2922854', 1),
+ (482, 'NOVA SOURE', 5, '2922904', 1),
+ (483, 'NOVA VICOSA', 5, '2923001', 1),
+ (484, 'NOVO HORIZONTE', 5, '2923035', 1),
+ (485, 'NOVO TRIUNFO', 5, '2923050', 1),
+ (486, 'OLINDINA', 5, '2923100', 1),
+ (487, 'OLIVEIRA DOS BREJINHOS', 5, '2923209', 1),
+ (488, 'OURICANGAS', 5, '2923308', 1),
+ (489, 'OUROLANDIA', 5, '2923357', 1),
+ (490, 'PALMAS DE MONTE ALTO', 5, '2923407', 1),
+ (491, 'PALMEIRAS', 5, '2923506', 1),
+ (492, 'PARAMIRIM', 5, '2923605', 1),
+ (493, 'PARATINGA', 5, '2923704', 1),
+ (494, 'PARIPIRANGA', 5, '2923803', 1),
+ (495, 'PAU BRASIL', 5, '2923902', 1),
+ (496, 'PAULO AFONSO', 5, '2924009', 1),
+ (497, 'PE DE SERRA', 5, '2924058', 1),
+ (498, 'PEDRAO', 5, '2924108', 1),
+ (499, 'PEDRO ALEXANDRE', 5, '2924207', 1),
+ (500, 'PIATA', 5, '2924306', 1),
+ (501, 'PILAO ARCADO', 5, '2924405', 1),
+ (502, 'PINDAI', 5, '2924504', 1),
+ (503, 'PINDOBACU', 5, '2924603', 1),
+ (504, 'PINTADAS', 5, '2924652', 1),
+ (505, 'PIRAI DO NORTE', 5, '2924678', 1),
+ (506, 'PIRIPA', 5, '2924702', 1),
+ (507, 'PIRITIBA', 5, '2924801', 1),
+ (508, 'PLANALTINO', 5, '2924900', 1),
+ (509, 'PLANALTO', 5, '2925006', 1),
+ (510, 'POCOES', 5, '2925105', 1),
+ (511, 'POJUCA', 5, '2925204', 1),
+ (512, 'PONTO NOVO', 5, '2925253', 1),
+ (513, 'PORTO SEGURO', 5, '2925303', 1),
+ (514, 'POTIRAGUA', 5, '2925402', 1),
+ (515, 'PRADO', 5, '2925501', 1),
+ (516, 'PRESIDENTE DUTRA', 5, '2925600', 1),
+ (517, 'PRESIDENTE JANIO QUADROS', 5, '2925709', 1),
+ (518, 'PRESIDENTE TANCREDO NEVES', 5, '2925758', 1),
+ (519, 'QUEIMADAS', 5, '2925808', 1),
+ (520, 'QUIJINGUE', 5, '2925907', 1),
+ (521, 'QUIXABEIRA', 5, '2925931', 1),
+ (522, 'RAFAEL JAMBEIRO', 5, '2925956', 1),
+ (523, 'REMANSO', 5, '2926004', 1),
+ (524, 'RETIROLANDIA', 5, '2926103', 1),
+ (525, 'RIACHAO DAS NEVES', 5, '2926202', 1),
+ (526, 'RIACHAO DO JACUIPE', 5, '2926301', 1),
+ (527, 'RIACHO DE SANTANA', 5, '2926400', 1),
+ (528, 'RIBEIRA DO AMPARO', 5, '2926509', 1),
+ (529, 'RIBEIRA DO POMBAL', 5, '2926608', 1),
+ (530, 'RIBEIRAO DO LARGO', 5, '2926657', 1),
+ (531, 'RIO DE CONTAS', 5, '2926707', 1),
+ (532, 'RIO DO ANTONIO', 5, '2926806', 1),
+ (533, 'RIO DO PIRES', 5, '2926905', 1),
+ (534, 'RIO REAL', 5, '2927002', 1),
+ (535, 'RODELAS', 5, '2927101', 1),
+ (536, 'RUY BARBOSA', 5, '2927200', 1),
+ (537, 'SALINAS DA MARGARIDA', 5, '2927309', 1),
+ (538, 'SALVADOR', 5, '2927408', 1),
+ (539, 'SANTA BARBARA', 5, '2927507', 1),
+ (540, 'SANTA BRIGIDA', 5, '2927606', 1),
+ (541, 'SANTA CRUZ CABRALIA', 5, '2927705', 1),
+ (542, 'SANTA CRUZ DA VITORIA', 5, '2927804', 1),
+ (543, 'SANTA INES', 5, '2927903', 1),
+ (544, 'SANTALUZ', 5, '2928000', 1),
+ (545, 'SANTA LUZIA', 5, '2928059', 1),
+ (546, 'SANTA MARIA DA VITORIA', 5, '2928109', 1),
+ (547, 'SANTANA', 5, '2928208', 1),
+ (548, 'SANTANOPOLIS', 5, '2928307', 1),
+ (549, 'SANTA RITA DE CASSIA', 5, '2928406', 1),
+ (550, 'SANTA TERESINHA', 5, '2928505', 1),
+ (551, 'SANTO AMARO', 5, '2928604', 1),
+ (552, 'SANTO ANTONIO DE JESUS', 5, '2928703', 1),
+ (553, 'SANTO ESTEVAO', 5, '2928802', 1),
+ (554, 'SAO DESIDERIO', 5, '2928901', 1),
+ (555, 'SAO DOMINGOS', 5, '2928950', 1),
+ (556, 'SAO FELIX', 5, '2929008', 1),
+ (557, 'SAO FELIX DO CORIBE', 5, '2929057', 1),
+ (558, 'SAO FELIPE', 5, '2929107', 1),
+ (559, 'SAO FRANCISCO DO CONDE', 5, '2929206', 1),
+ (560, 'SAO GABRIEL', 5, '2929255', 1),
+ (561, 'SAO GONCALO DOS CAMPOS', 5, '2929305', 1),
+ (562, 'SAO JOSE DA VITORIA', 5, '2929354', 1),
+ (563, 'SAO JOSE DO JACUIPE', 5, '2929370', 1),
+ (564, 'SAO MIGUEL DAS MATAS', 5, '2929404', 1),
+ (565, 'SAO SEBASTIAO DO PASSE', 5, '2929503', 1),
+ (566, 'SAPEACU', 5, '2929602', 1),
+ (567, 'SATIRO DIAS', 5, '2929701', 1),
+ (568, 'SAUBARA', 5, '2929750', 1),
+ (569, 'SAUDE', 5, '2929800', 1),
+ (570, 'SEABRA', 5, '2929909', 1),
+ (571, 'SEBASTIAO LARANJEIRAS', 5, '2930006', 1),
+ (572, 'SENHOR DO BONFIM', 5, '2930105', 1),
+ (573, 'SERRA DO RAMALHO', 5, '2930154', 1),
+ (574, 'SENTO SE', 5, '2930204', 1),
+ (575, 'SERRA DOURADA', 5, '2930303', 1),
+ (576, 'SERRA PRETA', 5, '2930402', 1),
+ (577, 'SERRINHA', 5, '2930501', 1),
+ (578, 'SERROLANDIA', 5, '2930600', 1),
+ (579, 'SIMOES FILHO', 5, '2930709', 1),
+ (580, 'SITIO DO MATO', 5, '2930758', 1),
+ (581, 'SITIO DO QUINTO', 5, '2930766', 1),
+ (582, 'SOBRADINHO', 5, '2930774', 1),
+ (583, 'SOUTO SOARES', 5, '2930808', 1),
+ (584, 'TABOCAS DO BREJO VELHO', 5, '2930907', 1),
+ (585, 'TANHACU', 5, '2931004', 1),
+ (586, 'TANQUE NOVO', 5, '2931053', 1),
+ (587, 'TANQUINHO', 5, '2931103', 1),
+ (588, 'TAPEROA', 5, '2931202', 1),
+ (589, 'TAPIRAMUTA', 5, '2931301', 1),
+ (590, 'TEIXEIRA DE FREITAS', 5, '2931350', 1),
+ (591, 'TEODORO SAMPAIO', 5, '2931400', 1),
+ (592, 'TEOFILANDIA', 5, '2931509', 1),
+ (593, 'TEOLANDIA', 5, '2931608', 1),
+ (594, 'TERRA NOVA', 5, '2931707', 1),
+ (595, 'TREMEDAL', 5, '2931806', 1),
+ (596, 'TUCANO', 5, '2931905', 1),
+ (597, 'UAUA', 5, '2932002', 1),
+ (598, 'UBAIRA', 5, '2932101', 1),
+ (599, 'UBAITABA', 5, '2932200', 1),
+ (600, 'UBATA', 5, '2932309', 1),
+ (601, 'UIBAI', 5, '2932408', 1),
+ (602, 'UMBURANAS', 5, '2932457', 1),
+ (603, 'UNA', 5, '2932507', 1),
+ (604, 'URANDI', 5, '2932606', 1),
+ (605, 'URUCUCA', 5, '2932705', 1),
+ (606, 'UTINGA', 5, '2932804', 1),
+ (607, 'VALENCA', 5, '2932903', 1),
+ (608, 'VALENTE', 5, '2933000', 1),
+ (609, 'VARZEA DA ROCA', 5, '2933059', 1),
+ (610, 'VARZEA DO POCO', 5, '2933109', 1),
+ (611, 'VARZEA NOVA', 5, '2933158', 1),
+ (612, 'VARZEDO', 5, '2933174', 1),
+ (613, 'VERA CRUZ', 5, '2933208', 1),
+ (614, 'VEREDA', 5, '2933257', 1),
+ (615, 'VITORIA DA CONQUISTA', 5, '2933307', 1),
+ (616, 'WAGNER', 5, '2933406', 1),
+ (617, 'WANDERLEY', 5, '2933455', 1),
+ (618, 'WENCESLAU GUIMARAES', 5, '2933505', 1),
+ (619, 'XIQUE-XIQUE', 5, '2933604', 1),
+ (620, 'ABAIARA', 6, '2300101', 1),
+ (621, 'ACARAPE', 6, '2300150', 1),
+ (622, 'ACARAU', 6, '2300200', 1),
+ (623, 'ACOPIARA', 6, '2300309', 1),
+ (624, 'AIUABA', 6, '2300408', 1),
+ (625, 'ALCANTARAS', 6, '2300507', 1),
+ (626, 'ALTANEIRA', 6, '2300606', 1),
+ (627, 'ALTO SANTO', 6, '2300705', 1),
+ (628, 'AMONTADA', 6, '2300754', 1),
+ (629, 'ANTONINA DO NORTE', 6, '2300804', 1),
+ (630, 'APUIARES', 6, '2300903', 1),
+ (631, 'AQUIRAZ', 6, '2301000', 1),
+ (632, 'ARACATI', 6, '2301109', 1),
+ (633, 'ARACOIABA', 6, '2301208', 1),
+ (634, 'ARARENDA', 6, '2301257', 1),
+ (635, 'ARARIPE', 6, '2301307', 1),
+ (636, 'ARATUBA', 6, '2301406', 1),
+ (637, 'ARNEIROZ', 6, '2301505', 1),
+ (638, 'ASSARE', 6, '2301604', 1),
+ (639, 'AURORA', 6, '2301703', 1),
+ (640, 'BAIXIO', 6, '2301802', 1),
+ (641, 'BANABUIU', 6, '2301851', 1),
+ (642, 'BARBALHA', 6, '2301901', 1),
+ (643, 'BARREIRA', 6, '2301950', 1),
+ (644, 'BARRO', 6, '2302008', 1),
+ (645, 'BARROQUINHA', 6, '2302057', 1),
+ (646, 'BATURITE', 6, '2302107', 1),
+ (647, 'BEBERIBE', 6, '2302206', 1),
+ (648, 'BELA CRUZ', 6, '2302305', 1),
+ (649, 'BOA VIAGEM', 6, '2302404', 1),
+ (650, 'BREJO SANTO', 6, '2302503', 1),
+ (651, 'CAMOCIM', 6, '2302602', 1),
+ (652, 'CAMPOS SALES', 6, '2302701', 1),
+ (653, 'CANINDE', 6, '2302800', 1),
+ (654, 'CAPISTRANO', 6, '2302909', 1),
+ (655, 'CARIDADE', 6, '2303006', 1),
+ (656, 'CARIRE', 6, '2303105', 1),
+ (657, 'CARIRIACU', 6, '2303204', 1),
+ (658, 'CARIUS', 6, '2303303', 1),
+ (659, 'CARNAUBAL', 6, '2303402', 1),
+ (660, 'CASCAVEL', 6, '2303501', 1),
+ (661, 'CATARINA', 6, '2303600', 1),
+ (662, 'CATUNDA', 6, '2303659', 1),
+ (663, 'CAUCAIA', 6, '2303709', 1),
+ (664, 'CEDRO', 6, '2303808', 1),
+ (665, 'CHAVAL', 6, '2303907', 1),
+ (666, 'CHORO', 6, '2303931', 1),
+ (667, 'CHOROZINHO', 6, '2303956', 1),
+ (668, 'COREAU', 6, '2304004', 1),
+ (669, 'CRATEUS', 6, '2304103', 1),
+ (670, 'CRATO', 6, '2304202', 1),
+ (671, 'CROATA', 6, '2304236', 1),
+ (672, 'CRUZ', 6, '2304251', 1),
+ (673, 'DEPUTADO IRAPUAN PINHEIRO', 6, '2304269', 1),
+ (674, 'ERERE', 6, '2304277', 1),
+ (675, 'EUSEBIO', 6, '2304285', 1),
+ (676, 'FARIAS BRITO', 6, '2304301', 1),
+ (677, 'FORQUILHA', 6, '2304350', 1),
+ (678, 'FORTALEZA', 6, '2304400', 1),
+ (679, 'FORTIM', 6, '2304459', 1),
+ (680, 'FRECHEIRINHA', 6, '2304509', 1),
+ (681, 'GENERAL SAMPAIO', 6, '2304608', 1),
+ (682, 'GRACA', 6, '2304657', 1),
+ (683, 'GRANJA', 6, '2304707', 1),
+ (684, 'GRANJEIRO', 6, '2304806', 1),
+ (685, 'GROAIRAS', 6, '2304905', 1),
+ (686, 'GUAIUBA', 6, '2304954', 1),
+ (687, 'GUARACIABA DO NORTE', 6, '2305001', 1),
+ (688, 'GUARAMIRANGA', 6, '2305100', 1),
+ (689, 'HIDROLANDIA', 6, '2305209', 1),
+ (690, 'HORIZONTE', 6, '2305233', 1),
+ (691, 'IBARETAMA', 6, '2305266', 1),
+ (692, 'IBIAPINA', 6, '2305308', 1),
+ (693, 'IBICUITINGA', 6, '2305332', 1),
+ (694, 'ICAPUI', 6, '2305357', 1),
+ (695, 'ICO', 6, '2305407', 1),
+ (696, 'IGUATU', 6, '2305506', 1),
+ (697, 'INDEPENDENCIA', 6, '2305605', 1),
+ (698, 'IPAPORANGA', 6, '2305654', 1),
+ (699, 'IPAUMIRIM', 6, '2305704', 1),
+ (700, 'IPU', 6, '2305803', 1),
+ (701, 'IPUEIRAS', 6, '2305902', 1),
+ (702, 'IRACEMA', 6, '2306009', 1),
+ (703, 'IRAUCUBA', 6, '2306108', 1),
+ (704, 'ITAICABA', 6, '2306207', 1),
+ (705, 'ITAITINGA', 6, '2306256', 1),
+ (706, 'ITAPAGE', 6, '2306306', 1),
+ (707, 'ITAPIPOCA', 6, '2306405', 1),
+ (708, 'ITAPIUNA', 6, '2306504', 1),
+ (709, 'ITAREMA', 6, '2306553', 1),
+ (710, 'ITATIRA', 6, '2306603', 1),
+ (711, 'JAGUARETAMA', 6, '2306702', 1),
+ (712, 'JAGUARIBARA', 6, '2306801', 1),
+ (713, 'JAGUARIBE', 6, '2306900', 1),
+ (714, 'JAGUARUANA', 6, '2307007', 1),
+ (715, 'JARDIM', 6, '2307106', 1),
+ (716, 'JATI', 6, '2307205', 1),
+ (717, 'JIJOCA DE JERICOACOARA', 6, '2307254', 1),
+ (718, 'JUAZEIRO DO NORTE', 6, '2307304', 1),
+ (719, 'JUCAS', 6, '2307403', 1),
+ (720, 'LAVRAS DA MANGABEIRA', 6, '2307502', 1),
+ (721, 'LIMOEIRO DO NORTE', 6, '2307601', 1),
+ (722, 'MADALENA', 6, '2307635', 1),
+ (723, 'MARACANAU', 6, '2307650', 1),
+ (724, 'MARANGUAPE', 6, '2307700', 1),
+ (725, 'MARCO', 6, '2307809', 1),
+ (726, 'MARTINOPOLE', 6, '2307908', 1),
+ (727, 'MASSAPE', 6, '2308005', 1),
+ (728, 'MAURITI', 6, '2308104', 1),
+ (729, 'MERUOCA', 6, '2308203', 1),
+ (730, 'MILAGRES', 6, '2308302', 1),
+ (731, 'MILHA', 6, '2308351', 1),
+ (732, 'MIRAIMA', 6, '2308377', 1),
+ (733, 'MISSAO VELHA', 6, '2308401', 1),
+ (734, 'MOMBACA', 6, '2308500', 1),
+ (735, 'MONSENHOR TABOSA', 6, '2308609', 1),
+ (736, 'MORADA NOVA', 6, '2308708', 1),
+ (737, 'MORAUJO', 6, '2308807', 1),
+ (738, 'MORRINHOS', 6, '2308906', 1),
+ (739, 'MUCAMBO', 6, '2309003', 1),
+ (740, 'MULUNGU', 6, '2309102', 1),
+ (741, 'NOVA OLINDA', 6, '2309201', 1),
+ (742, 'NOVA RUSSAS', 6, '2309300', 1),
+ (743, 'NOVO ORIENTE', 6, '2309409', 1),
+ (744, 'OCARA', 6, '2309458', 1),
+ (745, 'OROS', 6, '2309508', 1),
+ (746, 'PACAJUS', 6, '2309607', 1),
+ (747, 'PACATUBA', 6, '2309706', 1),
+ (748, 'PACOTI', 6, '2309805', 1),
+ (749, 'PACUJA', 6, '2309904', 1),
+ (750, 'PALHANO', 6, '2310001', 1),
+ (751, 'PALMACIA', 6, '2310100', 1),
+ (752, 'PARACURU', 6, '2310209', 1),
+ (753, 'PARAIPABA', 6, '2310258', 1),
+ (754, 'PARAMBU', 6, '2310308', 1),
+ (755, 'PARAMOTI', 6, '2310407', 1),
+ (756, 'PEDRA BRANCA', 6, '2310506', 1),
+ (757, 'PENAFORTE', 6, '2310605', 1),
+ (758, 'PENTECOSTE', 6, '2310704', 1),
+ (759, 'PEREIRO', 6, '2310803', 1),
+ (760, 'PINDORETAMA', 6, '2310852', 1),
+ (761, 'PIQUET CARNEIRO', 6, '2310902', 1),
+ (762, 'PIRES FERREIRA', 6, '2310951', 1),
+ (763, 'PORANGA', 6, '2311009', 1),
+ (764, 'PORTEIRAS', 6, '2311108', 1),
+ (765, 'POTENGI', 6, '2311207', 1),
+ (766, 'POTIRETAMA', 6, '2311231', 1),
+ (767, 'QUITERIANOPOLIS', 6, '2311264', 1),
+ (768, 'QUIXADA', 6, '2311306', 1),
+ (769, 'QUIXELO', 6, '2311355', 1),
+ (770, 'QUIXERAMOBIM', 6, '2311405', 1),
+ (771, 'QUIXERE', 6, '2311504', 1),
+ (772, 'REDENCAO', 6, '2311603', 1),
+ (773, 'RERIUTABA', 6, '2311702', 1),
+ (774, 'RUSSAS', 6, '2311801', 1),
+ (775, 'SABOEIRO', 6, '2311900', 1),
+ (776, 'SALITRE', 6, '2311959', 1),
+ (777, 'SANTANA DO ACARAU', 6, '2312007', 1),
+ (778, 'SANTANA DO CARIRI', 6, '2312106', 1),
+ (779, 'SANTA QUITERIA', 6, '2312205', 1),
+ (780, 'SAO BENEDITO', 6, '2312304', 1),
+ (781, 'SAO GONCALO DO AMARANTE', 6, '2312403', 1),
+ (782, 'SAO JOAO DO JAGUARIBE', 6, '2312502', 1),
+ (783, 'SAO LUIS DO CURU', 6, '2312601', 1),
+ (784, 'SENADOR POMPEU', 6, '2312700', 1),
+ (785, 'SENADOR SA', 6, '2312809', 1),
+ (786, 'SOBRAL', 6, '2312908', 1),
+ (787, 'SOLONOPOLE', 6, '2313005', 1),
+ (788, 'TABULEIRO DO NORTE', 6, '2313104', 1),
+ (789, 'TAMBORIL', 6, '2313203', 1),
+ (790, 'TARRAFAS', 6, '2313252', 1),
+ (791, 'TAUA', 6, '2313302', 1),
+ (792, 'TEJUCUOCA', 6, '2313351', 1),
+ (793, 'TIANGUA', 6, '2313401', 1),
+ (794, 'TRAIRI', 6, '2313500', 1),
+ (795, 'TURURU', 6, '2313559', 1),
+ (796, 'UBAJARA', 6, '2313609', 1),
+ (797, 'UMARI', 6, '2313708', 1),
+ (798, 'UMIRIM', 6, '2313757', 1),
+ (799, 'URUBURETAMA', 6, '2313807', 1),
+ (800, 'URUOCA', 6, '2313906', 1),
+ (801, 'VARJOTA', 6, '2313955', 1),
+ (802, 'VARZEA ALEGRE', 6, '2314003', 1),
+ (803, 'VICOSA DO CEARA', 6, '2314102', 1),
+ (804, 'BRASILIA', 7, '5300108', 1),
+ (805, 'AFONSO CLAUDIO', 8, '3200102', 1),
+ (806, 'AGUIA BRANCA', 8, '3200136', 1),
+ (807, 'AGUA DOCE DO NORTE', 8, '3200169', 1),
+ (808, 'ALEGRE', 8, '3200201', 1),
+ (809, 'ALFREDO CHAVES', 8, '3200300', 1),
+ (810, 'ALTO RIO NOVO', 8, '3200359', 1),
+ (811, 'ANCHIETA', 8, '3200409', 1),
+ (812, 'APIACA', 8, '3200508', 1),
+ (813, 'ARACRUZ', 8, '3200607', 1),
+ (814, 'ATILIO VIVACQUA', 8, '3200706', 1),
+ (815, 'BAIXO GUANDU', 8, '3200805', 1),
+ (816, 'BARRA DE SAO FRANCISCO', 8, '3200904', 1),
+ (817, 'BOA ESPERANCA', 8, '3201001', 1),
+ (818, 'BOM JESUS DO NORTE', 8, '3201100', 1),
+ (819, 'BREJETUBA', 8, '3201159', 1),
+ (820, 'CACHOEIRO DE ITAPEMIRIM', 8, '3201209', 1),
+ (821, 'CARIACICA', 8, '3201308', 1),
+ (822, 'CASTELO', 8, '3201407', 1),
+ (823, 'COLATINA', 8, '3201506', 1),
+ (824, 'CONCEICAO DA BARRA', 8, '3201605', 1),
+ (825, 'CONCEICAO DO CASTELO', 8, '3201704', 1),
+ (826, 'DIVINO DE SAO LOURENCO', 8, '3201803', 1),
+ (827, 'DOMINGOS MARTINS', 8, '3201902', 1),
+ (828, 'DORES DO RIO PRETO', 8, '3202009', 1),
+ (829, 'ECOPORANGA', 8, '3202108', 1),
+ (830, 'FUNDAO', 8, '3202207', 1),
+ (831, 'GOVERNADOR LINDENBERG', 8, '3202256', 1),
+ (832, 'GUACUI', 8, '3202306', 1),
+ (833, 'GUARAPARI', 8, '3202405', 1),
+ (834, 'IBATIBA', 8, '3202454', 1),
+ (835, 'IBIRACU', 8, '3202504', 1),
+ (836, 'IBITIRAMA', 8, '3202553', 1),
+ (837, 'ICONHA', 8, '3202603', 1),
+ (838, 'IRUPI', 8, '3202652', 1),
+ (839, 'ITAGUACU', 8, '3202702', 1),
+ (840, 'ITAPEMIRIM', 8, '3202801', 1),
+ (841, 'ITARANA', 8, '3202900', 1),
+ (842, 'IUNA', 8, '3203007', 1),
+ (843, 'JAGUARE', 8, '3203056', 1),
+ (844, 'JERONIMO MONTEIRO', 8, '3203106', 1),
+ (845, 'JOAO NEIVA', 8, '3203130', 1),
+ (846, 'LARANJA DA TERRA', 8, '3203163', 1),
+ (847, 'LINHARES', 8, '3203205', 1),
+ (848, 'MANTENOPOLIS', 8, '3203304', 1),
+ (849, 'MARATAIZES', 8, '3203320', 1),
+ (850, 'MARECHAL FLORIANO', 8, '3203346', 1),
+ (851, 'MARILANDIA', 8, '3203353', 1),
+ (852, 'MIMOSO DO SUL', 8, '3203403', 1),
+ (853, 'MONTANHA', 8, '3203502', 1),
+ (854, 'MUCURICI', 8, '3203601', 1),
+ (855, 'MUNIZ FREIRE', 8, '3203700', 1),
+ (856, 'MUQUI', 8, '3203809', 1),
+ (857, 'NOVA VENECIA', 8, '3203908', 1),
+ (858, 'PANCAS', 8, '3204005', 1),
+ (859, 'PEDRO CANARIO', 8, '3204054', 1),
+ (860, 'PINHEIROS', 8, '3204104', 1),
+ (861, 'PIUMA', 8, '3204203', 1),
+ (862, 'PONTO BELO', 8, '3204252', 1),
+ (863, 'PRESIDENTE KENNEDY', 8, '3204302', 1),
+ (864, 'RIO BANANAL', 8, '3204351', 1),
+ (865, 'RIO NOVO DO SUL', 8, '3204401', 1),
+ (866, 'SANTA LEOPOLDINA', 8, '3204500', 1),
+ (867, 'SANTA MARIA DE JETIBA', 8, '3204559', 1),
+ (868, 'SANTA TERESA', 8, '3204609', 1),
+ (869, 'SAO DOMINGOS DO NORTE', 8, '3204658', 1),
+ (870, 'SAO GABRIEL DA PALHA', 8, '3204708', 1),
+ (871, 'SAO JOSE DO CALCADO', 8, '3204807', 1),
+ (872, 'SAO MATEUS', 8, '3204906', 1),
+ (873, 'SAO ROQUE DO CANAA', 8, '3204955', 1),
+ (874, 'SERRA', 8, '3205002', 1),
+ (875, 'SOORETAMA', 8, '3205010', 1),
+ (876, 'VARGEM ALTA', 8, '3205036', 1),
+ (877, 'VENDA NOVA DO IMIGRANTE', 8, '3205069', 1),
+ (878, 'VIANA', 8, '3205101', 1),
+ (879, 'VILA PAVAO', 8, '3205150', 1),
+ (880, 'VILA VALERIO', 8, '3205176', 1),
+ (881, 'VILA VELHA', 8, '3205200', 1),
+ (882, 'VITORIA', 8, '3205309', 1),
+ (883, 'ABADIA DE GOIAS', 9, '5200050', 1),
+ (884, 'ABADIANIA', 9, '5200100', 1),
+ (885, 'ACREUNA', 9, '5200134', 1),
+ (886, 'ADELANDIA', 9, '5200159', 1),
+ (887, 'AGUA FRIA DE GOIAS', 9, '5200175', 1),
+ (888, 'AGUA LIMPA', 9, '5200209', 1),
+ (889, 'AGUAS LINDAS DE GOIAS', 9, '5200258', 1),
+ (890, 'ALEXANIA', 9, '5200308', 1),
+ (891, 'ALOANDIA', 9, '5200506', 1),
+ (892, 'ALTO HORIZONTE', 9, '5200555', 1),
+ (893, 'ALTO PARAISO DE GOIAS', 9, '5200605', 1),
+ (894, 'ALVORADA DO NORTE', 9, '5200803', 1),
+ (895, 'AMARALINA', 9, '5200829', 1),
+ (896, 'AMERICANO DO BRASIL', 9, '5200852', 1),
+ (897, 'AMORINOPOLIS', 9, '5200902', 1),
+ (898, 'ANAPOLIS', 9, '5201108', 1),
+ (899, 'ANHANGUERA', 9, '5201207', 1),
+ (900, 'ANICUNS', 9, '5201306', 1),
+ (901, 'APARECIDA DE GOIANIA', 9, '5201405', 1),
+ (902, 'APARECIDA DO RIO DOCE', 9, '5201454', 1),
+ (903, 'APORE', 9, '5201504', 1),
+ (904, 'ARACU', 9, '5201603', 1),
+ (905, 'ARAGARCAS', 9, '5201702', 1),
+ (906, 'ARAGOIANIA', 9, '5201801', 1),
+ (907, 'ARAGUAPAZ', 9, '5202155', 1),
+ (908, 'ARENOPOLIS', 9, '5202353', 1),
+ (909, 'ARUANA', 9, '5202502', 1),
+ (910, 'AURILANDIA', 9, '5202601', 1),
+ (911, 'AVELINOPOLIS', 9, '5202809', 1),
+ (912, 'BALIZA', 9, '5203104', 1),
+ (913, 'BARRO ALTO', 9, '5203203', 1),
+ (914, 'BELA VISTA DE GOIAS', 9, '5203302', 1),
+ (915, 'BOM JARDIM DE GOIAS', 9, '5203401', 1),
+ (916, 'BOM JESUS DE GOIAS', 9, '5203500', 1),
+ (917, 'BONFINOPOLIS', 9, '5203559', 1),
+ (918, 'BONOPOLIS', 9, '5203575', 1),
+ (919, 'BRAZABRANTES', 9, '5203609', 1),
+ (920, 'BRITANIA', 9, '5203807', 1),
+ (921, 'BURITI ALEGRE', 9, '5203906', 1),
+ (922, 'BURITI DE GOIAS', 9, '5203939', 1),
+ (923, 'BURITINOPOLIS', 9, '5203962', 1),
+ (924, 'CABECEIRAS', 9, '5204003', 1),
+ (925, 'CACHOEIRA ALTA', 9, '5204102', 1),
+ (926, 'CACHOEIRA DE GOIAS', 9, '5204201', 1),
+ (927, 'CACHOEIRA DOURADA', 9, '5204250', 1),
+ (928, 'CACU', 9, '5204300', 1),
+ (929, 'CAIAPONIA', 9, '5204409', 1),
+ (930, 'CALDAS NOVAS', 9, '5204508', 1),
+ (931, 'CALDAZINHA', 9, '5204557', 1),
+ (932, 'CAMPESTRE DE GOIAS', 9, '5204607', 1),
+ (933, 'CAMPINACU', 9, '5204656', 1),
+ (934, 'CAMPINORTE', 9, '5204706', 1),
+ (935, 'CAMPO ALEGRE DE GOIAS', 9, '5204805', 1),
+ (936, 'CAMPO LIMPO DE GOIAS', 9, '5204854', 1),
+ (937, 'CAMPOS BELOS', 9, '5204904', 1),
+ (938, 'CAMPOS VERDES', 9, '5204953', 1),
+ (939, 'CARMO DO RIO VERDE', 9, '5205000', 1),
+ (940, 'CASTELANDIA', 9, '5205059', 1),
+ (941, 'CATALAO', 9, '5205109', 1),
+ (942, 'CATURAI', 9, '5205208', 1),
+ (943, 'CAVALCANTE', 9, '5205307', 1),
+ (944, 'CERES', 9, '5205406', 1),
+ (945, 'CEZARINA', 9, '5205455', 1),
+ (946, 'CHAPADAO DO CEU', 9, '5205471', 1),
+ (947, 'CIDADE OCIDENTAL', 9, '5205497', 1),
+ (948, 'COCALZINHO DE GOIAS', 9, '5205513', 1),
+ (949, 'COLINAS DO SUL', 9, '5205521', 1),
+ (950, 'CORREGO DO OURO', 9, '5205703', 1),
+ (951, 'CORUMBA DE GOIAS', 9, '5205802', 1),
+ (952, 'CORUMBAIBA', 9, '5205901', 1),
+ (953, 'CRISTALINA', 9, '5206206', 1),
+ (954, 'CRISTIANOPOLIS', 9, '5206305', 1),
+ (955, 'CRIXAS', 9, '5206404', 1),
+ (956, 'CROMINIA', 9, '5206503', 1),
+ (957, 'CUMARI', 9, '5206602', 1),
+ (958, 'DAMIANOPOLIS', 9, '5206701', 1),
+ (959, 'DAMOLANDIA', 9, '5206800', 1),
+ (960, 'DAVINOPOLIS', 9, '5206909', 1),
+ (961, 'DIORAMA', 9, '5207105', 1),
+ (962, 'DOVERLANDIA', 9, '5207253', 1),
+ (963, 'EDEALINA', 9, '5207352', 1),
+ (964, 'EDEIA', 9, '5207402', 1),
+ (965, 'ESTRELA DO NORTE', 9, '5207501', 1),
+ (966, 'FAINA', 9, '5207535', 1),
+ (967, 'FAZENDA NOVA', 9, '5207600', 1),
+ (968, 'FIRMINOPOLIS', 9, '5207808', 1),
+ (969, 'FLORES DE GOIAS', 9, '5207907', 1),
+ (970, 'FORMOSA', 9, '5208004', 1),
+ (971, 'FORMOSO', 9, '5208103', 1),
+ (972, 'GAMELEIRA DE GOIAS', 9, '5208152', 1),
+ (973, 'DIVINOPOLIS DE GOIAS', 9, '5208301', 1),
+ (974, 'GOIANAPOLIS', 9, '5208400', 1),
+ (975, 'GOIANDIRA', 9, '5208509', 1),
+ (976, 'GOIANESIA', 9, '5208608', 1),
+ (977, 'GOIANIA', 9, '5208707', 1),
+ (978, 'GOIANIRA', 9, '5208806', 1),
+ (979, 'GOIAS', 9, '5208905', 1),
+ (980, 'GOIATUBA', 9, '5209101', 1),
+ (981, 'GOUVELANDIA', 9, '5209150', 1),
+ (982, 'GUAPO', 9, '5209200', 1),
+ (983, 'GUARAITA', 9, '5209291', 1),
+ (984, 'GUARANI DE GOIAS', 9, '5209408', 1),
+ (985, 'GUARINOS', 9, '5209457', 1),
+ (986, 'HEITORAI', 9, '5209606', 1),
+ (987, 'HIDROLANDIA', 9, '5209705', 1),
+ (988, 'HIDROLINA', 9, '5209804', 1),
+ (989, 'IACIARA', 9, '5209903', 1),
+ (990, 'INACIOLANDIA', 9, '5209937', 1),
+ (991, 'INDIARA', 9, '5209952', 1),
+ (992, 'INHUMAS', 9, '5210000', 1),
+ (993, 'IPAMERI', 9, '5210109', 1),
+ (994, 'IPIRANGA DE GOIAS', 9, '5210158', 1),
+ (995, 'IPORA', 9, '5210208', 1),
+ (996, 'ISRAELANDIA', 9, '5210307', 1),
+ (997, 'ITABERAI', 9, '5210406', 1),
+ (998, 'ITAGUARI', 9, '5210562', 1),
+ (999, 'ITAGUARU', 9, '5210604', 1),
+ (1000, 'ITAJA', 9, '5210802', 1),
+ (1001, 'ITAPACI', 9, '5210901', 1),
+ (1002, 'ITAPIRAPUA', 9, '5211008', 1),
+ (1003, 'ITAPURANGA', 9, '5211206', 1),
+ (1004, 'ITARUMA', 9, '5211305', 1),
+ (1005, 'BOILERPLATECU', 9, '5211404', 1),
+ (1006, 'ITUMBIARA', 9, '5211503', 1),
+ (1007, 'IVOLANDIA', 9, '5211602', 1),
+ (1008, 'JANDAIA', 9, '5211701', 1),
+ (1009, 'JARAGUA', 9, '5211800', 1),
+ (1010, 'JATAI', 9, '5211909', 1),
+ (1011, 'JAUPACI', 9, '5212006', 1),
+ (1012, 'JESUPOLIS', 9, '5212055', 1),
+ (1013, 'JOVIANIA', 9, '5212105', 1),
+ (1014, 'JUSSARA', 9, '5212204', 1),
+ (1015, 'LAGOA SANTA', 9, '5212253', 1),
+ (1016, 'LEOPOLDO DE BULHOES', 9, '5212303', 1),
+ (1017, 'LUZIANIA', 9, '5212501', 1),
+ (1018, 'MAIRIPOTABA', 9, '5212600', 1),
+ (1019, 'MAMBAI', 9, '5212709', 1),
+ (1020, 'MARA ROSA', 9, '5212808', 1),
+ (1021, 'MARZAGAO', 9, '5212907', 1),
+ (1022, 'MATRINCHA', 9, '5212956', 1),
+ (1023, 'MAURILANDIA', 9, '5213004', 1),
+ (1024, 'MIMOSO DE GOIAS', 9, '5213053', 1),
+ (1025, 'MINACU', 9, '5213087', 1),
+ (1026, 'MINEIROS', 9, '5213103', 1),
+ (1027, 'MOIPORA', 9, '5213400', 1),
+ (1028, 'MONTE ALEGRE DE GOIAS', 9, '5213509', 1),
+ (1029, 'MONTES CLAROS DE GOIAS', 9, '5213707', 1),
+ (1030, 'MONTIVIDIU', 9, '5213756', 1),
+ (1031, 'MONTIVIDIU DO NORTE', 9, '5213772', 1),
+ (1032, 'MORRINHOS', 9, '5213806', 1),
+ (1033, 'MORRO AGUDO DE GOIAS', 9, '5213855', 1),
+ (1034, 'MOSSAMEDES', 9, '5213905', 1),
+ (1035, 'MOZARLANDIA', 9, '5214002', 1),
+ (1036, 'MUNDO NOVO', 9, '5214051', 1),
+ (1037, 'MUTUNOPOLIS', 9, '5214101', 1),
+ (1038, 'NAZARIO', 9, '5214408', 1),
+ (1039, 'NEROPOLIS', 9, '5214507', 1),
+ (1040, 'NIQUELANDIA', 9, '5214606', 1),
+ (1041, 'NOVA AMERICA', 9, '5214705', 1),
+ (1042, 'NOVA AURORA', 9, '5214804', 1),
+ (1043, 'NOVA CRIXAS', 9, '5214838', 1),
+ (1044, 'NOVA GLORIA', 9, '5214861', 1),
+ (1045, 'NOVA IGUACU DE GOIAS', 9, '5214879', 1),
+ (1046, 'NOVA ROMA', 9, '5214903', 1),
+ (1047, 'NOVA VENEZA', 9, '5215009', 1),
+ (1048, 'NOVO BRASIL', 9, '5215207', 1),
+ (1049, 'NOVO GAMA', 9, '5215231', 1),
+ (1050, 'NOVO PLANALTO', 9, '5215256', 1),
+ (1051, 'ORIZONA', 9, '5215306', 1),
+ (1052, 'OURO VERDE DE GOIAS', 9, '5215405', 1),
+ (1053, 'OUVIDOR', 9, '5215504', 1),
+ (1054, 'PADRE BERNARDO', 9, '5215603', 1),
+ (1055, 'PALESTINA DE GOIAS', 9, '5215652', 1),
+ (1056, 'PALMEIRAS DE GOIAS', 9, '5215702', 1),
+ (1057, 'PALMELO', 9, '5215801', 1),
+ (1058, 'PALMINOPOLIS', 9, '5215900', 1),
+ (1059, 'PANAMA', 9, '5216007', 1),
+ (1060, 'PARANAIGUARA', 9, '5216304', 1),
+ (1061, 'PARAUNA', 9, '5216403', 1),
+ (1062, 'PEROLANDIA', 9, '5216452', 1),
+ (1063, 'PETROLINA DE GOIAS', 9, '5216809', 1),
+ (1064, 'PILAR DE GOIAS', 9, '5216908', 1),
+ (1065, 'PIRACANJUBA', 9, '5217104', 1),
+ (1066, 'PIRANHAS', 9, '5217203', 1),
+ (1067, 'PIRENOPOLIS', 9, '5217302', 1),
+ (1068, 'PIRES DO RIO', 9, '5217401', 1),
+ (1069, 'PLANALTINA', 9, '5217609', 1),
+ (1070, 'PONTALINA', 9, '5217708', 1),
+ (1071, 'PORANGATU', 9, '5218003', 1),
+ (1072, 'PORTEIRAO', 9, '5218052', 1),
+ (1073, 'PORTELANDIA', 9, '5218102', 1),
+ (1074, 'POSSE', 9, '5218300', 1),
+ (1075, 'PROFESSOR JAMIL', 9, '5218391', 1),
+ (1076, 'QUIRINOPOLIS', 9, '5218508', 1),
+ (1077, 'RIALMA', 9, '5218607', 1),
+ (1078, 'RIANAPOLIS', 9, '5218706', 1),
+ (1079, 'RIO QUENTE', 9, '5218789', 1),
+ (1080, 'RIO VERDE', 9, '5218805', 1),
+ (1081, 'RUBIATABA', 9, '5218904', 1),
+ (1082, 'SANCLERLANDIA', 9, '5219001', 1),
+ (1083, 'SANTA BARBARA DE GOIAS', 9, '5219100', 1),
+ (1084, 'SANTA CRUZ DE GOIAS', 9, '5219209', 1),
+ (1085, 'SANTA FE DE GOIAS', 9, '5219258', 1),
+ (1086, 'SANTA HELENA DE GOIAS', 9, '5219308', 1),
+ (1087, 'SANTA ISABEL', 9, '5219357', 1),
+ (1088, 'SANTA RITA DO ARAGUAIA', 9, '5219407', 1),
+ (1089, 'SANTA RITA DO NOVO DESTINO', 9, '5219456', 1),
+ (1090, 'SANTA ROSA DE GOIAS', 9, '5219506', 1),
+ (1091, 'SANTA TEREZA DE GOIAS', 9, '5219605', 1),
+ (1092, 'SANTA TEREZINHA DE GOIAS', 9, '5219704', 1),
+ (1093, 'SANTO ANTONIO DA BARRA', 9, '5219712', 1),
+ (1094, 'SANTO ANTONIO DE GOIAS', 9, '5219738', 1),
+ (1095, 'SANTO ANTONIO DO DESCOBERTO', 9, '5219753', 1),
+ (1096, 'SAO DOMINGOS', 9, '5219803', 1),
+ (1097, 'SAO FRANCISCO DE GOIAS', 9, '5219902', 1),
+ (1098, 'SAO JOAO DALIANCA', 9, '5220009', 1),
+ (1099, 'SAO JOAO DA PARAUNA', 9, '5220058', 1),
+ (1100, 'SAO LUIS DE MONTES BELOS', 9, '5220108', 1),
+ (1101, 'SAO LUIZ DO NORTE', 9, '5220157', 1),
+ (1102, 'SAO MIGUEL DO ARAGUAIA', 9, '5220207', 1),
+ (1103, 'SAO MIGUEL DO PASSA QUATRO', 9, '5220264', 1),
+ (1104, 'SAO PATRICIO', 9, '5220280', 1),
+ (1105, 'SAO SIMAO', 9, '5220405', 1),
+ (1106, 'SENADOR CANEDO', 9, '5220454', 1),
+ (1107, 'SERRANOPOLIS', 9, '5220504', 1),
+ (1108, 'SILVANIA', 9, '5220603', 1),
+ (1109, 'SIMOLANDIA', 9, '5220686', 1),
+ (1110, 'SITIO DABADIA', 9, '5220702', 1),
+ (1111, 'TAQUARAL DE GOIAS', 9, '5221007', 1),
+ (1112, 'TERESINA DE GOIAS', 9, '5221080', 1),
+ (1113, 'TEREZOPOLIS DE GOIAS', 9, '5221197', 1),
+ (1114, 'TRES RANCHOS', 9, '5221304', 1),
+ (1115, 'TRINDADE', 9, '5221403', 1),
+ (1116, 'TROMBAS', 9, '5221452', 1),
+ (1117, 'TURVANIA', 9, '5221502', 1),
+ (1118, 'TURVELANDIA', 9, '5221551', 1),
+ (1119, 'UIRAPURU', 9, '5221577', 1),
+ (1120, 'URUACU', 9, '5221601', 1),
+ (1121, 'URUANA', 9, '5221700', 1),
+ (1122, 'URUTAI', 9, '5221809', 1),
+ (1123, 'VALPARAISO DE GOIAS', 9, '5221858', 1),
+ (1124, 'VARJAO', 9, '5221908', 1),
+ (1125, 'VIANOPOLIS', 9, '5222005', 1),
+ (1126, 'VICENTINOPOLIS', 9, '5222054', 1),
+ (1127, 'VILA BOA', 9, '5222203', 1),
+ (1128, 'VILA PROPICIO', 9, '5222302', 1),
+ (1129, 'ACAILANDIA', 10, '2100055', 1),
+ (1130, 'AFONSO CUNHA', 10, '2100105', 1),
+ (1131, 'AGUA DOCE DO MARANHAO', 10, '2100154', 1),
+ (1132, 'ALCANTARA', 10, '2100204', 1),
+ (1133, 'ALDEIAS ALTAS', 10, '2100303', 1),
+ (1134, 'ALTAMIRA DO MARANHAO', 10, '2100402', 1),
+ (1135, 'ALTO ALEGRE DO MARANHAO', 10, '2100436', 1),
+ (1136, 'ALTO ALEGRE DO PINDARE', 10, '2100477', 1),
+ (1137, 'ALTO PARNAIBA', 10, '2100501', 1),
+ (1138, 'AMAPA DO MARANHAO', 10, '2100550', 1),
+ (1139, 'AMARANTE DO MARANHAO', 10, '2100600', 1),
+ (1140, 'ANAJATUBA', 10, '2100709', 1),
+ (1141, 'ANAPURUS', 10, '2100808', 1),
+ (1142, 'APICUM-ACU', 10, '2100832', 1),
+ (1143, 'ARAGUANA', 10, '2100873', 1),
+ (1144, 'ARAIOSES', 10, '2100907', 1),
+ (1145, 'ARAME', 10, '2100956', 1),
+ (1146, 'ARARI', 10, '2101004', 1),
+ (1147, 'AXIXA', 10, '2101103', 1),
+ (1148, 'BACABAL', 10, '2101202', 1),
+ (1149, 'BACABEIRA', 10, '2101251', 1),
+ (1150, 'BACURI', 10, '2101301', 1),
+ (1151, 'BACURITUBA', 10, '2101350', 1),
+ (1152, 'BALSAS', 10, '2101400', 1),
+ (1153, 'BARAO DE GRAJAU', 10, '2101509', 1),
+ (1154, 'BARRA DO CORDA', 10, '2101608', 1),
+ (1155, 'BARREIRINHAS', 10, '2101707', 1),
+ (1156, 'BELAGUA', 10, '2101731', 1),
+ (1157, 'BELA VISTA DO MARANHAO', 10, '2101772', 1),
+ (1158, 'BENEDITO LEITE', 10, '2101806', 1),
+ (1159, 'BEQUIMAO', 10, '2101905', 1),
+ (1160, 'BERNARDO DO MEARIM', 10, '2101939', 1),
+ (1161, 'BOA VISTA DO GURUPI', 10, '2101970', 1),
+ (1162, 'BOM JARDIM', 10, '2102002', 1),
+ (1163, 'BOM JESUS DAS SELVAS', 10, '2102036', 1),
+ (1164, 'BOM LUGAR', 10, '2102077', 1),
+ (1165, 'BREJO', 10, '2102101', 1),
+ (1166, 'BREJO DE AREIA', 10, '2102150', 1),
+ (1167, 'BURITI', 10, '2102200', 1),
+ (1168, 'BURITI BRAVO', 10, '2102309', 1),
+ (1169, 'BURITICUPU', 10, '2102325', 1),
+ (1170, 'BURITIRANA', 10, '2102358', 1),
+ (1171, 'CACHOEIRA GRANDE', 10, '2102374', 1),
+ (1172, 'CAJAPIO', 10, '2102408', 1),
+ (1173, 'CAJARI', 10, '2102507', 1),
+ (1174, 'CAMPESTRE DO MARANHAO', 10, '2102556', 1),
+ (1175, 'CANDIDO MENDES', 10, '2102606', 1),
+ (1176, 'CANTANHEDE', 10, '2102705', 1),
+ (1177, 'CAPINZAL DO NORTE', 10, '2102754', 1),
+ (1178, 'CAROLINA', 10, '2102804', 1),
+ (1179, 'CARUTAPERA', 10, '2102903', 1),
+ (1180, 'CAXIAS', 10, '2103000', 1),
+ (1181, 'CEDRAL', 10, '2103109', 1),
+ (1182, 'CENTRAL DO MARANHAO', 10, '2103125', 1),
+ (1183, 'CENTRO DO GUILHERME', 10, '2103158', 1),
+ (1184, 'CENTRO NOVO DO MARANHAO', 10, '2103174', 1),
+ (1185, 'CHAPADINHA', 10, '2103208', 1),
+ (1186, 'CIDELANDIA', 10, '2103257', 1),
+ (1187, 'CODO', 10, '2103307', 1),
+ (1188, 'COELHO NETO', 10, '2103406', 1),
+ (1189, 'COLINAS', 10, '2103505', 1),
+ (1190, 'CONCEICAO DO LAGO-ACU', 10, '2103554', 1),
+ (1191, 'COROATA', 10, '2103604', 1),
+ (1192, 'CURURUPU', 10, '2103703', 1),
+ (1193, 'DAVINOPOLIS', 10, '2103752', 1),
+ (1194, 'DOM PEDRO', 10, '2103802', 1),
+ (1195, 'DUQUE BACELAR', 10, '2103901', 1),
+ (1196, 'ESPERANTINOPOLIS', 10, '2104008', 1),
+ (1197, 'ESTREITO', 10, '2104057', 1),
+ (1198, 'FEIRA NOVA DO MARANHAO', 10, '2104073', 1),
+ (1199, 'FERNANDO FALCAO', 10, '2104081', 1),
+ (1200, 'FORMOSA DA SERRA NEGRA', 10, '2104099', 1),
+ (1201, 'FORTALEZA DOS NOGUEIRAS', 10, '2104107', 1),
+ (1202, 'FORTUNA', 10, '2104206', 1),
+ (1203, 'GODOFREDO VIANA', 10, '2104305', 1),
+ (1204, 'GONCALVES DIAS', 10, '2104404', 1),
+ (1205, 'GOVERNADOR ARCHER', 10, '2104503', 1),
+ (1206, 'GOVERNADOR EDISON LOBAO', 10, '2104552', 1),
+ (1207, 'GOVERNADOR EUGENIO BARROS', 10, '2104602', 1),
+ (1208, 'GOVERNADOR LUIZ ROCHA', 10, '2104628', 1),
+ (1209, 'GOVERNADOR NEWTON BELLO', 10, '2104651', 1),
+ (1210, 'GOVERNADOR NUNES FREIRE', 10, '2104677', 1),
+ (1211, 'GRACA ARANHA', 10, '2104701', 1),
+ (1212, 'GRAJAU', 10, '2104800', 1),
+ (1213, 'GUIMARAES', 10, '2104909', 1),
+ (1214, 'HUMBERTO DE CAMPOS', 10, '2105005', 1),
+ (1215, 'ICATU', 10, '2105104', 1),
+ (1216, 'IGARAPE DO MEIO', 10, '2105153', 1),
+ (1217, 'IGARAPE GRANDE', 10, '2105203', 1),
+ (1218, 'IMPERATRIZ', 10, '2105302', 1),
+ (1219, 'ITAIPAVA DO GRAJAU', 10, '2105351', 1),
+ (1220, 'ITAPECURU MIRIM', 10, '2105401', 1),
+ (1221, 'ITINGA DO MARANHAO', 10, '2105427', 1),
+ (1222, 'JATOBA', 10, '2105450', 1),
+ (1223, 'JENIPAPO DOS VIEIRAS', 10, '2105476', 1),
+ (1224, 'JOAO LISBOA', 10, '2105500', 1),
+ (1225, 'JOSELANDIA', 10, '2105609', 1),
+ (1226, 'JUNCO DO MARANHAO', 10, '2105658', 1),
+ (1227, 'LAGO DA PEDRA', 10, '2105708', 1),
+ (1228, 'LAGO DO JUNCO', 10, '2105807', 1),
+ (1229, 'LAGO VERDE', 10, '2105906', 1),
+ (1230, 'LAGOA DO MATO', 10, '2105922', 1),
+ (1231, 'LAGO DOS RODRIGUES', 10, '2105948', 1),
+ (1232, 'LAGOA GRANDE DO MARANHAO', 10, '2105963', 1),
+ (1233, 'LAJEADO NOVO', 10, '2105989', 1),
+ (1234, 'LIMA CAMPOS', 10, '2106003', 1),
+ (1235, 'LORETO', 10, '2106102', 1),
+ (1236, 'LUIS DOMINGUES', 10, '2106201', 1),
+ (1237, 'MAGALHAES DE ALMEIDA', 10, '2106300', 1),
+ (1238, 'MARACACUME', 10, '2106326', 1),
+ (1239, 'MARAJA DO SENA', 10, '2106359', 1),
+ (1240, 'MARANHAOZINHO', 10, '2106375', 1),
+ (1241, 'MATA ROMA', 10, '2106409', 1),
+ (1242, 'MATINHA', 10, '2106508', 1),
+ (1243, 'MATOES', 10, '2106607', 1),
+ (1244, 'MATOES DO NORTE', 10, '2106631', 1),
+ (1245, 'MILAGRES DO MARANHAO', 10, '2106672', 1),
+ (1246, 'MIRADOR', 10, '2106706', 1),
+ (1247, 'MIRANDA DO NORTE', 10, '2106755', 1),
+ (1248, 'MIRINZAL', 10, '2106805', 1),
+ (1249, 'MONCAO', 10, '2106904', 1),
+ (1250, 'MONTES ALTOS', 10, '2107001', 1),
+ (1251, 'MORROS', 10, '2107100', 1),
+ (1252, 'NINA RODRIGUES', 10, '2107209', 1),
+ (1253, 'NOVA COLINAS', 10, '2107258', 1),
+ (1254, 'NOVA IORQUE', 10, '2107308', 1),
+ (1255, 'NOVA OLINDA DO MARANHAO', 10, '2107357', 1),
+ (1256, 'OLHO DAGUA DAS CUNHAS', 10, '2107407', 1),
+ (1257, 'OLINDA NOVA DO MARANHAO', 10, '2107456', 1),
+ (1258, 'PACO DO LUMIAR', 10, '2107506', 1),
+ (1259, 'PALMEIRANDIA', 10, '2107605', 1),
+ (1260, 'PARAIBANO', 10, '2107704', 1),
+ (1261, 'PARNARAMA', 10, '2107803', 1),
+ (1262, 'PASSAGEM FRANCA', 10, '2107902', 1),
+ (1263, 'PASTOS BONS', 10, '2108009', 1),
+ (1264, 'PAULINO NEVES', 10, '2108058', 1),
+ (1265, 'PAULO RAMOS', 10, '2108108', 1),
+ (1266, 'PEDREIRAS', 10, '2108207', 1),
+ (1267, 'PEDRO DO ROSARIO', 10, '2108256', 1),
+ (1268, 'PENALVA', 10, '2108306', 1),
+ (1269, 'PERI MIRIM', 10, '2108405', 1),
+ (1270, 'PERITORO', 10, '2108454', 1),
+ (1271, 'PINDARE-MIRIM', 10, '2108504', 1),
+ (1272, 'PINHEIRO', 10, '2108603', 1),
+ (1273, 'PIO XII', 10, '2108702', 1),
+ (1274, 'PIRAPEMAS', 10, '2108801', 1),
+ (1275, 'POCAO DE PEDRAS', 10, '2108900', 1),
+ (1276, 'PORTO FRANCO', 10, '2109007', 1),
+ (1277, 'PORTO RICO DO MARANHAO', 10, '2109056', 1),
+ (1278, 'PRESIDENTE DUTRA', 10, '2109106', 1),
+ (1279, 'PRESIDENTE JUSCELINO', 10, '2109205', 1),
+ (1280, 'PRESIDENTE MEDICI', 10, '2109239', 1),
+ (1281, 'PRESIDENTE SARNEY', 10, '2109270', 1),
+ (1282, 'PRESIDENTE VARGAS', 10, '2109304', 1),
+ (1283, 'PRIMEIRA CRUZ', 10, '2109403', 1),
+ (1284, 'RAPOSA', 10, '2109452', 1),
+ (1285, 'RIACHAO', 10, '2109502', 1),
+ (1286, 'RIBAMAR FIQUENE', 10, '2109551', 1),
+ (1287, 'ROSARIO', 10, '2109601', 1),
+ (1288, 'SAMBAIBA', 10, '2109700', 1),
+ (1289, 'SANTA FILOMENA DO MARANHAO', 10, '2109759', 1),
+ (1290, 'SANTA HELENA', 10, '2109809', 1),
+ (1291, 'SANTA INES', 10, '2109908', 1),
+ (1292, 'SANTA LUZIA', 10, '2110005', 1),
+ (1293, 'SANTA LUZIA DO PARUA', 10, '2110039', 1),
+ (1294, 'SANTA QUITERIA DO MARANHAO', 10, '2110104', 1),
+ (1295, 'SANTA RITA', 10, '2110203', 1),
+ (1296, 'SANTANA DO MARANHAO', 10, '2110237', 1),
+ (1297, 'SANTO AMARO DO MARANHAO', 10, '2110278', 1),
+ (1298, 'SANTO ANTONIO DOS LOPES', 10, '2110302', 1),
+ (1299, 'SAO BENEDITO DO RIO PRETO', 10, '2110401', 1),
+ (1300, 'SAO BENTO', 10, '2110500', 1),
+ (1301, 'SAO BERNARDO', 10, '2110609', 1),
+ (1302, 'SAO DOMINGOS DO AZEITAO', 10, '2110658', 1),
+ (1303, 'SAO DOMINGOS DO MARANHAO', 10, '2110708', 1),
+ (1304, 'SAO FELIX DE BALSAS', 10, '2110807', 1),
+ (1305, 'SAO FRANCISCO DO BREJAO', 10, '2110856', 1),
+ (1306, 'SAO FRANCISCO DO MARANHAO', 10, '2110906', 1),
+ (1307, 'SAO JOAO BATISTA', 10, '2111003', 1),
+ (1308, 'SAO JOAO DO CARU', 10, '2111029', 1),
+ (1309, 'SAO JOAO DO PARAISO', 10, '2111052', 1),
+ (1310, 'SAO JOAO DO SOTER', 10, '2111078', 1),
+ (1311, 'SAO JOAO DOS PATOS', 10, '2111102', 1),
+ (1312, 'SAO JOSE DE RIBAMAR', 10, '2111201', 1),
+ (1313, 'SAO JOSE DOS BASILIOS', 10, '2111250', 1),
+ (1314, 'SAO LUIS', 10, '2111300', 1),
+ (1315, 'SAO LUIS GONZAGA DO MARANHAO', 10, '2111409', 1),
+ (1316, 'SAO MATEUS DO MARANHAO', 10, '2111508', 1),
+ (1317, 'SAO PEDRO DA AGUA BRANCA', 10, '2111532', 1),
+ (1318, 'SAO PEDRO DOS CRENTES', 10, '2111573', 1),
+ (1319, 'SAO RAIMUNDO DAS MANGABEIRAS', 10, '2111607', 1),
+ (1320, 'SAO RAIMUNDO DO DOCA BEZERRA', 10, '2111631', 1),
+ (1321, 'SAO ROBERTO', 10, '2111672', 1),
+ (1322, 'SAO VICENTE FERRER', 10, '2111706', 1),
+ (1323, 'SATUBINHA', 10, '2111722', 1),
+ (1324, 'SENADOR ALEXANDRE COSTA', 10, '2111748', 1),
+ (1325, 'SENADOR LA ROCQUE', 10, '2111763', 1),
+ (1326, 'SERRANO DO MARANHAO', 10, '2111789', 1),
+ (1327, 'SITIO NOVO', 10, '2111805', 1),
+ (1328, 'SUCUPIRA DO NORTE', 10, '2111904', 1),
+ (1329, 'SUCUPIRA DO RIACHAO', 10, '2111953', 1),
+ (1330, 'TASSO FRAGOSO', 10, '2112001', 1),
+ (1331, 'TIMBIRAS', 10, '2112100', 1),
+ (1332, 'TIMON', 10, '2112209', 1),
+ (1333, 'TRIZIDELA DO VALE', 10, '2112233', 1),
+ (1334, 'TUFILANDIA', 10, '2112274', 1),
+ (1335, 'TUNTUM', 10, '2112308', 1),
+ (1336, 'TURIACU', 10, '2112407', 1),
+ (1337, 'TURILANDIA', 10, '2112456', 1),
+ (1338, 'TUTOIA', 10, '2112506', 1),
+ (1339, 'URBANO SANTOS', 10, '2112605', 1),
+ (1340, 'VARGEM GRANDE', 10, '2112704', 1),
+ (1341, 'VIANA', 10, '2112803', 1),
+ (1342, 'VILA NOVA DOS MARTIRIOS', 10, '2112852', 1),
+ (1343, 'VITORIA DO MEARIM', 10, '2112902', 1),
+ (1344, 'VITORINO FREIRE', 10, '2113009', 1),
+ (1345, 'ZE DOCA', 10, '2114007', 1),
+ (1346, 'ABADIA DOS DOURADOS', 11, '3100104', 1),
+ (1347, 'ABAETE', 11, '3100203', 1),
+ (1348, 'ABRE CAMPO', 11, '3100302', 1),
+ (1349, 'ACAIACA', 11, '3100401', 1),
+ (1350, 'ACUCENA', 11, '3100500', 1),
+ (1351, 'AGUA BOA', 11, '3100609', 1),
+ (1352, 'AGUA COMPRIDA', 11, '3100708', 1),
+ (1353, 'AGUANIL', 11, '3100807', 1),
+ (1354, 'AGUAS FORMOSAS', 11, '3100906', 1),
+ (1355, 'AGUAS VERMELHAS', 11, '3101003', 1),
+ (1356, 'AIMORES', 11, '3101102', 1),
+ (1357, 'AIURUOCA', 11, '3101201', 1),
+ (1358, 'ALAGOA', 11, '3101300', 1),
+ (1359, 'ALBERTINA', 11, '3101409', 1),
+ (1360, 'ALEM PARAIBA', 11, '3101508', 1),
+ (1361, 'ALFENAS', 11, '3101607', 1),
+ (1362, 'ALFREDO VASCONCELOS', 11, '3101631', 1),
+ (1363, 'ALMENARA', 11, '3101706', 1),
+ (1364, 'ALPERCATA', 11, '3101805', 1),
+ (1365, 'ALPINOPOLIS', 11, '3101904', 1),
+ (1366, 'ALTEROSA', 11, '3102001', 1),
+ (1367, 'ALTO CAPARAO', 11, '3102050', 1),
+ (1368, 'ALTO RIO DOCE', 11, '3102100', 1),
+ (1369, 'ALVARENGA', 11, '3102209', 1),
+ (1370, 'ALVINOPOLIS', 11, '3102308', 1),
+ (1371, 'ALVORADA DE MINAS', 11, '3102407', 1),
+ (1372, 'AMPARO DO SERRA', 11, '3102506', 1),
+ (1373, 'ANDRADAS', 11, '3102605', 1),
+ (1374, 'CACHOEIRA DE PAJEU', 11, '3102704', 1),
+ (1375, 'ANDRELANDIA', 11, '3102803', 1),
+ (1376, 'ANGELANDIA', 11, '3102852', 1),
+ (1377, 'ANTONIO CARLOS', 11, '3102902', 1),
+ (1378, 'ANTONIO DIAS', 11, '3103009', 1),
+ (1379, 'ANTONIO PRADO DE MINAS', 11, '3103108', 1),
+ (1380, 'ARACAI', 11, '3103207', 1),
+ (1381, 'ARACITABA', 11, '3103306', 1),
+ (1382, 'ARACUAI', 11, '3103405', 1),
+ (1383, 'ARAGUARI', 11, '3103504', 1),
+ (1384, 'ARANTINA', 11, '3103603', 1),
+ (1385, 'ARAPONGA', 11, '3103702', 1),
+ (1386, 'ARAPORA', 11, '3103751', 1),
+ (1387, 'ARAPUA', 11, '3103801', 1),
+ (1388, 'ARAUJOS', 11, '3103900', 1),
+ (1389, 'ARAXA', 11, '3104007', 1),
+ (1390, 'ARCEBURGO', 11, '3104106', 1),
+ (1391, 'ARCOS', 11, '3104205', 1),
+ (1392, 'AREADO', 11, '3104304', 1),
+ (1393, 'ARGIRITA', 11, '3104403', 1),
+ (1394, 'ARICANDUVA', 11, '3104452', 1),
+ (1395, 'ARINOS', 11, '3104502', 1),
+ (1396, 'ASTOLFO DUTRA', 11, '3104601', 1),
+ (1397, 'ATALEIA', 11, '3104700', 1),
+ (1398, 'AUGUSTO DE LIMA', 11, '3104809', 1),
+ (1399, 'BAEPENDI', 11, '3104908', 1),
+ (1400, 'BALDIM', 11, '3105004', 1),
+ (1401, 'BAMBUI', 11, '3105103', 1),
+ (1402, 'BANDEIRA', 11, '3105202', 1),
+ (1403, 'BANDEIRA DO SUL', 11, '3105301', 1),
+ (1404, 'BARAO DE COCAIS', 11, '3105400', 1),
+ (1405, 'BARAO DE MONTE ALTO', 11, '3105509', 1),
+ (1406, 'BARBACENA', 11, '3105608', 1),
+ (1407, 'BARRA LONGA', 11, '3105707', 1),
+ (1408, 'BARROSO', 11, '3105905', 1),
+ (1409, 'BELA VISTA DE MINAS', 11, '3106002', 1),
+ (1410, 'BELMIRO BRAGA', 11, '3106101', 1),
+ (1411, 'BELO HORIZONTE', 11, '3106200', 1),
+ (1412, 'BELO ORIENTE', 11, '3106309', 1),
+ (1413, 'BELO VALE', 11, '3106408', 1),
+ (1414, 'BERILO', 11, '3106507', 1),
+ (1415, 'BERTOPOLIS', 11, '3106606', 1),
+ (1416, 'BERIZAL', 11, '3106655', 1),
+ (1417, 'BETIM', 11, '3106705', 1),
+ (1418, 'BIAS FORTES', 11, '3106804', 1),
+ (1419, 'BICAS', 11, '3106903', 1),
+ (1420, 'BIQUINHAS', 11, '3107000', 1),
+ (1421, 'BOA ESPERANCA', 11, '3107109', 1),
+ (1422, 'BOCAINA DE MINAS', 11, '3107208', 1),
+ (1423, 'BOCAIUVA', 11, '3107307', 1),
+ (1424, 'BOM DESPACHO', 11, '3107406', 1),
+ (1425, 'BOM JARDIM DE MINAS', 11, '3107505', 1),
+ (1426, 'BOM JESUS DA PENHA', 11, '3107604', 1),
+ (1427, 'BOM JESUS DO AMPARO', 11, '3107703', 1),
+ (1428, 'BOM JESUS DO GALHO', 11, '3107802', 1),
+ (1429, 'BOM REPOUSO', 11, '3107901', 1),
+ (1430, 'BOM SUCESSO', 11, '3108008', 1),
+ (1431, 'BONFIM', 11, '3108107', 1),
+ (1432, 'BONFINOPOLIS DE MINAS', 11, '3108206', 1),
+ (1433, 'BONITO DE MINAS', 11, '3108255', 1),
+ (1434, 'BORDA DA MATA', 11, '3108305', 1),
+ (1435, 'BOTELHOS', 11, '3108404', 1),
+ (1436, 'BOTUMIRIM', 11, '3108503', 1),
+ (1437, 'BRASILANDIA DE MINAS', 11, '3108552', 1),
+ (1438, 'BRASILIA DE MINAS', 11, '3108602', 1),
+ (1439, 'BRAS PIRES', 11, '3108701', 1),
+ (1440, 'BRAUNAS', 11, '3108800', 1),
+ (1441, 'BRASOPOLIS', 11, '3108909', 1),
+ (1442, 'BRUMADINHO', 11, '3109006', 1),
+ (1443, 'BUENO BRANDAO', 11, '3109105', 1),
+ (1444, 'BUENOPOLIS', 11, '3109204', 1),
+ (1445, 'BUGRE', 11, '3109253', 1),
+ (1446, 'BURITIS', 11, '3109303', 1),
+ (1447, 'BURITIZEIRO', 11, '3109402', 1),
+ (1448, 'CABECEIRA GRANDE', 11, '3109451', 1),
+ (1449, 'CABO VERDE', 11, '3109501', 1),
+ (1450, 'CACHOEIRA DA PRATA', 11, '3109600', 1),
+ (1451, 'CACHOEIRA DE MINAS', 11, '3109709', 1),
+ (1452, 'CACHOEIRA DOURADA', 11, '3109808', 1),
+ (1453, 'CAETANOPOLIS', 11, '3109907', 1),
+ (1454, 'CAETE', 11, '3110004', 1),
+ (1455, 'CAIANA', 11, '3110103', 1),
+ (1456, 'CAJURI', 11, '3110202', 1),
+ (1457, 'CALDAS', 11, '3110301', 1),
+ (1458, 'CAMACHO', 11, '3110400', 1),
+ (1459, 'CAMANDUCAIA', 11, '3110509', 1),
+ (1460, 'CAMBUI', 11, '3110608', 1),
+ (1461, 'CAMBUQUIRA', 11, '3110707', 1),
+ (1462, 'CAMPANARIO', 11, '3110806', 1),
+ (1463, 'CAMPANHA', 11, '3110905', 1),
+ (1464, 'CAMPESTRE', 11, '3111002', 1),
+ (1465, 'CAMPINA VERDE', 11, '3111101', 1),
+ (1466, 'CAMPO AZUL', 11, '3111150', 1),
+ (1467, 'CAMPO BELO', 11, '3111200', 1),
+ (1468, 'CAMPO DO MEIO', 11, '3111309', 1),
+ (1469, 'CAMPO FLORIDO', 11, '3111408', 1),
+ (1470, 'CAMPOS ALTOS', 11, '3111507', 1),
+ (1471, 'CAMPOS GERAIS', 11, '3111606', 1),
+ (1472, 'CANAA', 11, '3111705', 1),
+ (1473, 'CANAPOLIS', 11, '3111804', 1),
+ (1474, 'CANA VERDE', 11, '3111903', 1),
+ (1475, 'CANDEIAS', 11, '3112000', 1),
+ (1476, 'CANTAGALO', 11, '3112059', 1),
+ (1477, 'CAPARAO', 11, '3112109', 1),
+ (1478, 'CAPELA NOVA', 11, '3112208', 1),
+ (1479, 'CAPELINHA', 11, '3112307', 1),
+ (1480, 'CAPETINGA', 11, '3112406', 1),
+ (1481, 'CAPIM BRANCO', 11, '3112505', 1),
+ (1482, 'CAPINOPOLIS', 11, '3112604', 1),
+ (1483, 'CAPITAO ANDRADE', 11, '3112653', 1),
+ (1484, 'CAPITAO ENEAS', 11, '3112703', 1),
+ (1485, 'CAPITOLIO', 11, '3112802', 1),
+ (1486, 'CAPUTIRA', 11, '3112901', 1),
+ (1487, 'CARAI', 11, '3113008', 1),
+ (1488, 'CARANAIBA', 11, '3113107', 1),
+ (1489, 'CARANDAI', 11, '3113206', 1),
+ (1490, 'CARANGOLA', 11, '3113305', 1),
+ (1491, 'CARATINGA', 11, '3113404', 1),
+ (1492, 'CARBONITA', 11, '3113503', 1),
+ (1493, 'CAREACU', 11, '3113602', 1),
+ (1494, 'CARLOS CHAGAS', 11, '3113701', 1),
+ (1495, 'CARMESIA', 11, '3113800', 1),
+ (1496, 'CARMO DA CACHOEIRA', 11, '3113909', 1),
+ (1497, 'CARMO DA MATA', 11, '3114006', 1),
+ (1498, 'CARMO DE MINAS', 11, '3114105', 1),
+ (1499, 'CARMO DO CAJURU', 11, '3114204', 1),
+ (1500, 'CARMO DO PARANAIBA', 11, '3114303', 1),
+ (1501, 'CARMO DO RIO CLARO', 11, '3114402', 1),
+ (1502, 'CARMOPOLIS DE MINAS', 11, '3114501', 1),
+ (1503, 'CARNEIRINHO', 11, '3114550', 1),
+ (1504, 'CARRANCAS', 11, '3114600', 1),
+ (1505, 'CARVALHOPOLIS', 11, '3114709', 1),
+ (1506, 'CARVALHOS', 11, '3114808', 1),
+ (1507, 'CASA GRANDE', 11, '3114907', 1),
+ (1508, 'CASCALHO RICO', 11, '3115003', 1),
+ (1509, 'CASSIA', 11, '3115102', 1),
+ (1510, 'CONCEICAO DA BARRA DE MINAS', 11, '3115201', 1),
+ (1511, 'CATAGUASES', 11, '3115300', 1),
+ (1512, 'CATAS ALTAS', 11, '3115359', 1),
+ (1513, 'CATAS ALTAS DA NORUEGA', 11, '3115409', 1),
+ (1514, 'CATUJI', 11, '3115458', 1),
+ (1515, 'CATUTI', 11, '3115474', 1),
+ (1516, 'CAXAMBU', 11, '3115508', 1),
+ (1517, 'CEDRO DO ABAETE', 11, '3115607', 1),
+ (1518, 'CENTRAL DE MINAS', 11, '3115706', 1),
+ (1519, 'CENTRALINA', 11, '3115805', 1),
+ (1520, 'CHACARA', 11, '3115904', 1),
+ (1521, 'CHALE', 11, '3116001', 1),
+ (1522, 'CHAPADA DO NORTE', 11, '3116100', 1),
+ (1523, 'CHAPADA GAUCHA', 11, '3116159', 1),
+ (1524, 'CHIADOR', 11, '3116209', 1),
+ (1525, 'CIPOTANEA', 11, '3116308', 1),
+ (1526, 'CLARAVAL', 11, '3116407', 1),
+ (1527, 'CLARO DOS POCOES', 11, '3116506', 1),
+ (1528, 'CLAUDIO', 11, '3116605', 1),
+ (1529, 'COIMBRA', 11, '3116704', 1),
+ (1530, 'COLUNA', 11, '3116803', 1),
+ (1531, 'COMENDADOR GOMES', 11, '3116902', 1),
+ (1532, 'COMERCINHO', 11, '3117009', 1),
+ (1533, 'CONCEICAO DA APARECIDA', 11, '3117108', 1),
+ (1534, 'CONCEICAO DAS PEDRAS', 11, '3117207', 1),
+ (1535, 'CONCEICAO DAS ALAGOAS', 11, '3117306', 1),
+ (1536, 'CONCEICAO DE IPANEMA', 11, '3117405', 1),
+ (1537, 'CONCEICAO DO MATO DENTRO', 11, '3117504', 1),
+ (1538, 'CONCEICAO DO PARA', 11, '3117603', 1),
+ (1539, 'CONCEICAO DO RIO VERDE', 11, '3117702', 1),
+ (1540, 'CONCEICAO DOS OUROS', 11, '3117801', 1),
+ (1541, 'CONEGO MARINHO', 11, '3117836', 1),
+ (1542, 'CONFINS', 11, '3117876', 1),
+ (1543, 'CONGONHAL', 11, '3117900', 1),
+ (1544, 'CONGONHAS', 11, '3118007', 1),
+ (1545, 'CONGONHAS DO NORTE', 11, '3118106', 1),
+ (1546, 'CONQUISTA', 11, '3118205', 1),
+ (1547, 'CONSELHEIRO LAFAIETE', 11, '3118304', 1),
+ (1548, 'CONSELHEIRO PENA', 11, '3118403', 1),
+ (1549, 'CONSOLACAO', 11, '3118502', 1),
+ (1550, 'CONTAGEM', 11, '3118601', 1),
+ (1551, 'COQUEIRAL', 11, '3118700', 1),
+ (1552, 'CORACAO DE JESUS', 11, '3118809', 1),
+ (1553, 'CORDISBURGO', 11, '3118908', 1),
+ (1554, 'CORDISLANDIA', 11, '3119005', 1),
+ (1555, 'CORINTO', 11, '3119104', 1),
+ (1556, 'COROACI', 11, '3119203', 1),
+ (1557, 'COROMANDEL', 11, '3119302', 1),
+ (1558, 'CORONEL FABRICIANO', 11, '3119401', 1),
+ (1559, 'CORONEL MURTA', 11, '3119500', 1),
+ (1560, 'CORONEL PACHECO', 11, '3119609', 1),
+ (1561, 'CORONEL XAVIER CHAVES', 11, '3119708', 1),
+ (1562, 'CORREGO DANTA', 11, '3119807', 1),
+ (1563, 'CORREGO DO BOM JESUS', 11, '3119906', 1),
+ (1564, 'CORREGO FUNDO', 11, '3119955', 1),
+ (1565, 'CORREGO NOVO', 11, '3120003', 1),
+ (1566, 'COUTO DE MAGALHAES DE MINAS', 11, '3120102', 1),
+ (1567, 'CRISOLITA', 11, '3120151', 1),
+ (1568, 'CRISTAIS', 11, '3120201', 1),
+ (1569, 'CRISTALIA', 11, '3120300', 1),
+ (1570, 'CRISTIANO OTONI', 11, '3120409', 1),
+ (1571, 'CRISTINA', 11, '3120508', 1),
+ (1572, 'CRUCILANDIA', 11, '3120607', 1),
+ (1573, 'CRUZEIRO DA FORTALEZA', 11, '3120706', 1),
+ (1574, 'CRUZILIA', 11, '3120805', 1),
+ (1575, 'CUPARAQUE', 11, '3120839', 1),
+ (1576, 'CURRAL DE DENTRO', 11, '3120870', 1),
+ (1577, 'CURVELO', 11, '3120904', 1),
+ (1578, 'DATAS', 11, '3121001', 1),
+ (1579, 'DELFIM MOREIRA', 11, '3121100', 1),
+ (1580, 'DELFINOPOLIS', 11, '3121209', 1),
+ (1581, 'DELTA', 11, '3121258', 1),
+ (1582, 'DESCOBERTO', 11, '3121308', 1),
+ (1583, 'DESTERRO DE ENTRE RIOS', 11, '3121407', 1),
+ (1584, 'DESTERRO DO MELO', 11, '3121506', 1),
+ (1585, 'DIAMANTINA', 11, '3121605', 1),
+ (1586, 'DIOGO DE VASCONCELOS', 11, '3121704', 1),
+ (1587, 'DIONISIO', 11, '3121803', 1),
+ (1588, 'DIVINESIA', 11, '3121902', 1),
+ (1589, 'DIVINO', 11, '3122009', 1),
+ (1590, 'DIVINO DAS LARANJEIRAS', 11, '3122108', 1),
+ (1591, 'DIVINOLANDIA DE MINAS', 11, '3122207', 1),
+ (1592, 'DIVINOPOLIS', 11, '3122306', 1),
+ (1593, 'DIVISA ALEGRE', 11, '3122355', 1),
+ (1594, 'DIVISA NOVA', 11, '3122405', 1),
+ (1595, 'DIVISOPOLIS', 11, '3122454', 1),
+ (1596, 'DOM BOSCO', 11, '3122470', 1),
+ (1597, 'DOM CAVATI', 11, '3122504', 1),
+ (1598, 'DOM JOAQUIM', 11, '3122603', 1),
+ (1599, 'DOM SILVERIO', 11, '3122702', 1),
+ (1600, 'DOM VICOSO', 11, '3122801', 1),
+ (1601, 'DONA EUSEBIA', 11, '3122900', 1),
+ (1602, 'DORES DE CAMPOS', 11, '3123007', 1),
+ (1603, 'DORES DE GUANHAES', 11, '3123106', 1),
+ (1604, 'DORES DO INDAIA', 11, '3123205', 1),
+ (1605, 'DORES DO TURVO', 11, '3123304', 1),
+ (1606, 'DORESOPOLIS', 11, '3123403', 1),
+ (1607, 'DOURADOQUARA', 11, '3123502', 1),
+ (1608, 'DURANDE', 11, '3123528', 1),
+ (1609, 'ELOI MENDES', 11, '3123601', 1),
+ (1610, 'ENGENHEIRO CALDAS', 11, '3123700', 1),
+ (1611, 'ENGENHEIRO NAVARRO', 11, '3123809', 1),
+ (1612, 'ENTRE FOLHAS', 11, '3123858', 1),
+ (1613, 'ENTRE RIOS DE MINAS', 11, '3123908', 1),
+ (1614, 'ERVALIA', 11, '3124005', 1),
+ (1615, 'ESMERALDAS', 11, '3124104', 1),
+ (1616, 'ESPERA FELIZ', 11, '3124203', 1),
+ (1617, 'ESPINOSA', 11, '3124302', 1),
+ (1618, 'ESPIRITO SANTO DO DOURADO', 11, '3124401', 1),
+ (1619, 'ESTIVA', 11, '3124500', 1),
+ (1620, 'ESTRELA DALVA', 11, '3124609', 1),
+ (1621, 'ESTRELA DO INDAIA', 11, '3124708', 1),
+ (1622, 'ESTRELA DO SUL', 11, '3124807', 1),
+ (1623, 'EUGENOPOLIS', 11, '3124906', 1),
+ (1624, 'EWBANK DA CAMARA', 11, '3125002', 1),
+ (1625, 'EXTREMA', 11, '3125101', 1),
+ (1626, 'FAMA', 11, '3125200', 1),
+ (1627, 'FARIA LEMOS', 11, '3125309', 1),
+ (1628, 'FELICIO DOS SANTOS', 11, '3125408', 1),
+ (1629, 'SAO GONCALO DO RIO PRETO', 11, '3125507', 1),
+ (1630, 'FELISBURGO', 11, '3125606', 1),
+ (1631, 'FELIXLANDIA', 11, '3125705', 1),
+ (1632, 'FERNANDES TOURINHO', 11, '3125804', 1),
+ (1633, 'FERROS', 11, '3125903', 1),
+ (1634, 'FERVEDOURO', 11, '3125952', 1),
+ (1635, 'FLORESTAL', 11, '3126000', 1),
+ (1636, 'FORMIGA', 11, '3126109', 1),
+ (1637, 'FORMOSO', 11, '3126208', 1),
+ (1638, 'FORTALEZA DE MINAS', 11, '3126307', 1),
+ (1639, 'FORTUNA DE MINAS', 11, '3126406', 1),
+ (1640, 'FRANCISCO BADARO', 11, '3126505', 1),
+ (1641, 'FRANCISCO DUMONT', 11, '3126604', 1),
+ (1642, 'FRANCISCO SA', 11, '3126703', 1),
+ (1643, 'FRANCISCOPOLIS', 11, '3126752', 1),
+ (1644, 'FREI GASPAR', 11, '3126802', 1),
+ (1645, 'FREI INOCENCIO', 11, '3126901', 1),
+ (1646, 'FREI LAGONEGRO', 11, '3126950', 1),
+ (1647, 'FRONTEIRA', 11, '3127008', 1),
+ (1648, 'FRONTEIRA DOS VALES', 11, '3127057', 1),
+ (1649, 'FRUTA DE LEITE', 11, '3127073', 1),
+ (1650, 'FRUTAL', 11, '3127107', 1),
+ (1651, 'FUNILANDIA', 11, '3127206', 1),
+ (1652, 'GALILEIA', 11, '3127305', 1),
+ (1653, 'GAMELEIRAS', 11, '3127339', 1),
+ (1654, 'GLAUCILANDIA', 11, '3127354', 1),
+ (1655, 'GOIABEIRA', 11, '3127370', 1),
+ (1656, 'GOIANA', 11, '3127388', 1),
+ (1657, 'GONCALVES', 11, '3127404', 1),
+ (1658, 'GONZAGA', 11, '3127503', 1),
+ (1659, 'GOUVEIA', 11, '3127602', 1),
+ (1660, 'GOVERNADOR VALADARES', 11, '3127701', 1),
+ (1661, 'GRAO MOGOL', 11, '3127800', 1),
+ (1662, 'GRUPIARA', 11, '3127909', 1),
+ (1663, 'GUANHAES', 11, '3128006', 1),
+ (1664, 'GUAPE', 11, '3128105', 1),
+ (1665, 'GUARACIABA', 11, '3128204', 1),
+ (1666, 'GUARACIAMA', 11, '3128253', 1),
+ (1667, 'GUARANESIA', 11, '3128303', 1),
+ (1668, 'GUARANI', 11, '3128402', 1),
+ (1669, 'GUARARA', 11, '3128501', 1),
+ (1670, 'GUARDA-MOR', 11, '3128600', 1),
+ (1671, 'GUAXUPE', 11, '3128709', 1),
+ (1672, 'GUIDOVAL', 11, '3128808', 1),
+ (1673, 'GUIMARANIA', 11, '3128907', 1),
+ (1674, 'GUIRICEMA', 11, '3129004', 1),
+ (1675, 'GURINHATA', 11, '3129103', 1),
+ (1676, 'HELIODORA', 11, '3129202', 1),
+ (1677, 'IAPU', 11, '3129301', 1),
+ (1678, 'IBERTIOGA', 11, '3129400', 1),
+ (1679, 'IBIA', 11, '3129509', 1),
+ (1680, 'IBIAI', 11, '3129608', 1),
+ (1681, 'IBIRACATU', 11, '3129657', 1),
+ (1682, 'IBIRACI', 11, '3129707', 1),
+ (1683, 'IBIRITE', 11, '3129806', 1),
+ (1684, 'IBITIURA DE MINAS', 11, '3129905', 1),
+ (1685, 'IBITURUNA', 11, '3130002', 1),
+ (1686, 'ICARAI DE MINAS', 11, '3130051', 1),
+ (1687, 'IGARAPE', 11, '3130101', 1),
+ (1688, 'IGARATINGA', 11, '3130200', 1),
+ (1689, 'IGUATAMA', 11, '3130309', 1),
+ (1690, 'IJACI', 11, '3130408', 1),
+ (1691, 'ILICINEA', 11, '3130507', 1),
+ (1692, 'IMBE DE MINAS', 11, '3130556', 1),
+ (1693, 'INCONFIDENTES', 11, '3130606', 1),
+ (1694, 'INDAIABIRA', 11, '3130655', 1),
+ (1695, 'INDIANOPOLIS', 11, '3130705', 1),
+ (1696, 'INGAI', 11, '3130804', 1),
+ (1697, 'INHAPIM', 11, '3130903', 1),
+ (1698, 'INHAUMA', 11, '3131000', 1),
+ (1699, 'INIMUTABA', 11, '3131109', 1),
+ (1700, 'IPABA', 11, '3131158', 1),
+ (1701, 'IPANEMA', 11, '3131208', 1),
+ (1702, 'IPATINGA', 11, '3131307', 1),
+ (1703, 'IPIACU', 11, '3131406', 1),
+ (1704, 'IPUIUNA', 11, '3131505', 1),
+ (1705, 'IRAI DE MINAS', 11, '3131604', 1),
+ (1706, 'ITABIRA', 11, '3131703', 1),
+ (1707, 'ITABIRINHA', 11, '3131802', 1),
+ (1708, 'ITABIRITO', 11, '3131901', 1),
+ (1709, 'ITACAMBIRA', 11, '3132008', 1),
+ (1710, 'ITACARAMBI', 11, '3132107', 1),
+ (1711, 'ITAGUARA', 11, '3132206', 1),
+ (1712, 'ITAIPE', 11, '3132305', 1),
+ (1713, 'ITAJUBA', 11, '3132404', 1),
+ (1714, 'ITAMARANDIBA', 11, '3132503', 1),
+ (1715, 'ITAMARATI DE MINAS', 11, '3132602', 1),
+ (1716, 'ITAMBACURI', 11, '3132701', 1),
+ (1717, 'ITAMBE DO MATO DENTRO', 11, '3132800', 1),
+ (1718, 'ITAMOGI', 11, '3132909', 1),
+ (1719, 'ITAMONTE', 11, '3133006', 1),
+ (1720, 'ITANHANDU', 11, '3133105', 1),
+ (1721, 'ITANHOMI', 11, '3133204', 1),
+ (1722, 'ITAOBIM', 11, '3133303', 1),
+ (1723, 'ITAPAGIPE', 11, '3133402', 1),
+ (1724, 'ITAPECERICA', 11, '3133501', 1),
+ (1725, 'ITAPEVA', 11, '3133600', 1),
+ (1726, 'ITATIAIUCU', 11, '3133709', 1),
+ (1727, 'BOILERPLATE DE MINAS', 11, '3133758', 1),
+ (1728, 'BOILERPLATENA', 11, '3133808', 1),
+ (1729, 'ITAVERAVA', 11, '3133907', 1),
+ (1730, 'ITINGA', 11, '3134004', 1),
+ (1731, 'ITUETA', 11, '3134103', 1),
+ (1732, 'ITUIUTABA', 11, '3134202', 1),
+ (1733, 'ITUMIRIM', 11, '3134301', 1),
+ (1734, 'ITURAMA', 11, '3134400', 1),
+ (1735, 'ITUTINGA', 11, '3134509', 1),
+ (1736, 'JABOTICATUBAS', 11, '3134608', 1),
+ (1737, 'JACINTO', 11, '3134707', 1),
+ (1738, 'JACUI', 11, '3134806', 1),
+ (1739, 'JACUTINGA', 11, '3134905', 1),
+ (1740, 'JAGUARACU', 11, '3135001', 1),
+ (1741, 'JAIBA', 11, '3135050', 1),
+ (1742, 'JAMPRUCA', 11, '3135076', 1),
+ (1743, 'JANAUBA', 11, '3135100', 1),
+ (1744, 'JANUARIA', 11, '3135209', 1),
+ (1745, 'JAPARAIBA', 11, '3135308', 1),
+ (1746, 'JAPONVAR', 11, '3135357', 1),
+ (1747, 'JECEABA', 11, '3135407', 1),
+ (1748, 'JENIPAPO DE MINAS', 11, '3135456', 1),
+ (1749, 'JEQUERI', 11, '3135506', 1),
+ (1750, 'JEQUITAI', 11, '3135605', 1),
+ (1751, 'JEQUITIBA', 11, '3135704', 1),
+ (1752, 'JEQUITINHONHA', 11, '3135803', 1),
+ (1753, 'JESUANIA', 11, '3135902', 1),
+ (1754, 'JOAIMA', 11, '3136009', 1),
+ (1755, 'JOANESIA', 11, '3136108', 1),
+ (1756, 'JOAO MONLEVADE', 11, '3136207', 1),
+ (1757, 'JOAO PINHEIRO', 11, '3136306', 1),
+ (1758, 'JOAQUIM FELICIO', 11, '3136405', 1),
+ (1759, 'JORDANIA', 11, '3136504', 1),
+ (1760, 'JOSE GONCALVES DE MINAS', 11, '3136520', 1),
+ (1761, 'JOSE RAYDAN', 11, '3136553', 1),
+ (1762, 'JOSENOPOLIS', 11, '3136579', 1),
+ (1763, 'NOVA UNIAO', 11, '3136603', 1),
+ (1764, 'JUATUBA', 11, '3136652', 1),
+ (1765, 'JUIZ DE FORA', 11, '3136702', 1),
+ (1766, 'JURAMENTO', 11, '3136801', 1),
+ (1767, 'JURUAIA', 11, '3136900', 1),
+ (1768, 'JUVENILIA', 11, '3136959', 1),
+ (1769, 'LADAINHA', 11, '3137007', 1),
+ (1770, 'LAGAMAR', 11, '3137106', 1),
+ (1771, 'LAGOA DA PRATA', 11, '3137205', 1),
+ (1772, 'LAGOA DOS PATOS', 11, '3137304', 1),
+ (1773, 'LAGOA DOURADA', 11, '3137403', 1),
+ (1774, 'LAGOA FORMOSA', 11, '3137502', 1),
+ (1775, 'LAGOA GRANDE', 11, '3137536', 1),
+ (1776, 'LAGOA SANTA', 11, '3137601', 1),
+ (1777, 'LAJINHA', 11, '3137700', 1),
+ (1778, 'LAMBARI', 11, '3137809', 1),
+ (1779, 'LAMIM', 11, '3137908', 1),
+ (1780, 'LARANJAL', 11, '3138005', 1),
+ (1781, 'LASSANCE', 11, '3138104', 1),
+ (1782, 'LAVRAS', 11, '3138203', 1),
+ (1783, 'LEANDRO FERREIRA', 11, '3138302', 1),
+ (1784, 'LEME DO PRADO', 11, '3138351', 1),
+ (1785, 'LEOPOLDINA', 11, '3138401', 1),
+ (1786, 'LIBERDADE', 11, '3138500', 1),
+ (1787, 'LIMA DUARTE', 11, '3138609', 1),
+ (1788, 'LIMEIRA DO OESTE', 11, '3138625', 1),
+ (1789, 'LONTRA', 11, '3138658', 1),
+ (1790, 'LUISBURGO', 11, '3138674', 1),
+ (1791, 'LUISLANDIA', 11, '3138682', 1),
+ (1792, 'LUMINARIAS', 11, '3138708', 1),
+ (1793, 'LUZ', 11, '3138807', 1),
+ (1794, 'MACHACALIS', 11, '3138906', 1),
+ (1795, 'MACHADO', 11, '3139003', 1),
+ (1796, 'MADRE DE DEUS DE MINAS', 11, '3139102', 1),
+ (1797, 'MALACACHETA', 11, '3139201', 1),
+ (1798, 'MAMONAS', 11, '3139250', 1),
+ (1799, 'MANGA', 11, '3139300', 1),
+ (1800, 'MANHUACU', 11, '3139409', 1),
+ (1801, 'MANHUMIRIM', 11, '3139508', 1),
+ (1802, 'MANTENA', 11, '3139607', 1),
+ (1803, 'MARAVILHAS', 11, '3139706', 1),
+ (1804, 'MAR DE ESPANHA', 11, '3139805', 1),
+ (1805, 'MARIA DA FE', 11, '3139904', 1),
+ (1806, 'MARIANA', 11, '3140001', 1),
+ (1807, 'MARILAC', 11, '3140100', 1),
+ (1808, 'MARIO CAMPOS', 11, '3140159', 1),
+ (1809, 'MARIPA DE MINAS', 11, '3140209', 1),
+ (1810, 'MARLIERIA', 11, '3140308', 1),
+ (1811, 'MARMELOPOLIS', 11, '3140407', 1),
+ (1812, 'MARTINHO CAMPOS', 11, '3140506', 1),
+ (1813, 'MARTINS SOARES', 11, '3140530', 1),
+ (1814, 'MATA VERDE', 11, '3140555', 1),
+ (1815, 'MATERLANDIA', 11, '3140605', 1),
+ (1816, 'MATEUS LEME', 11, '3140704', 1),
+ (1817, 'MATIAS BARBOSA', 11, '3140803', 1),
+ (1818, 'MATIAS CARDOSO', 11, '3140852', 1),
+ (1819, 'MATIPO', 11, '3140902', 1),
+ (1820, 'MATO VERDE', 11, '3141009', 1),
+ (1821, 'MATOZINHOS', 11, '3141108', 1),
+ (1822, 'MATUTINA', 11, '3141207', 1),
+ (1823, 'MEDEIROS', 11, '3141306', 1),
+ (1824, 'MEDINA', 11, '3141405', 1),
+ (1825, 'MENDES PIMENTEL', 11, '3141504', 1),
+ (1826, 'MERCES', 11, '3141603', 1),
+ (1827, 'MESQUITA', 11, '3141702', 1),
+ (1828, 'MINAS NOVAS', 11, '3141801', 1),
+ (1829, 'MINDURI', 11, '3141900', 1),
+ (1830, 'MIRABELA', 11, '3142007', 1),
+ (1831, 'MIRADOURO', 11, '3142106', 1),
+ (1832, 'MIRAI', 11, '3142205', 1),
+ (1833, 'MIRAVANIA', 11, '3142254', 1),
+ (1834, 'MOEDA', 11, '3142304', 1),
+ (1835, 'MOEMA', 11, '3142403', 1),
+ (1836, 'MONJOLOS', 11, '3142502', 1),
+ (1837, 'MONSENHOR PAULO', 11, '3142601', 1),
+ (1838, 'MONTALVANIA', 11, '3142700', 1),
+ (1839, 'MONTE ALEGRE DE MINAS', 11, '3142809', 1),
+ (1840, 'MONTE AZUL', 11, '3142908', 1),
+ (1841, 'MONTE BELO', 11, '3143005', 1),
+ (1842, 'MONTE CARMELO', 11, '3143104', 1),
+ (1843, 'MONTE FORMOSO', 11, '3143153', 1),
+ (1844, 'MONTE SANTO DE MINAS', 11, '3143203', 1),
+ (1845, 'MONTES CLAROS', 11, '3143302', 1),
+ (1846, 'MONTE SIAO', 11, '3143401', 1),
+ (1847, 'MONTEZUMA', 11, '3143450', 1),
+ (1848, 'MORADA NOVA DE MINAS', 11, '3143500', 1),
+ (1849, 'MORRO DA GARCA', 11, '3143609', 1),
+ (1850, 'MORRO DO PILAR', 11, '3143708', 1),
+ (1851, 'MUNHOZ', 11, '3143807', 1),
+ (1852, 'MURIAE', 11, '3143906', 1),
+ (1853, 'MUTUM', 11, '3144003', 1),
+ (1854, 'MUZAMBINHO', 11, '3144102', 1),
+ (1855, 'NACIP RAYDAN', 11, '3144201', 1),
+ (1856, 'NANUQUE', 11, '3144300', 1),
+ (1857, 'NAQUE', 11, '3144359', 1),
+ (1858, 'NATALANDIA', 11, '3144375', 1),
+ (1859, 'NATERCIA', 11, '3144409', 1),
+ (1860, 'NAZARENO', 11, '3144508', 1),
+ (1861, 'NEPOMUCENO', 11, '3144607', 1),
+ (1862, 'NINHEIRA', 11, '3144656', 1),
+ (1863, 'NOVA BELEM', 11, '3144672', 1),
+ (1864, 'NOVA ERA', 11, '3144706', 1),
+ (1865, 'NOVA LIMA', 11, '3144805', 1),
+ (1866, 'NOVA MODICA', 11, '3144904', 1),
+ (1867, 'NOVA PONTE', 11, '3145000', 1),
+ (1868, 'NOVA PORTEIRINHA', 11, '3145059', 1),
+ (1869, 'NOVA RESENDE', 11, '3145109', 1),
+ (1870, 'NOVA SERRANA', 11, '3145208', 1),
+ (1871, 'NOVO CRUZEIRO', 11, '3145307', 1),
+ (1872, 'NOVO ORIENTE DE MINAS', 11, '3145356', 1),
+ (1873, 'NOVORIZONTE', 11, '3145372', 1),
+ (1874, 'OLARIA', 11, '3145406', 1),
+ (1875, 'OLHOS-DAGUA', 11, '3145455', 1),
+ (1876, 'OLIMPIO NORONHA', 11, '3145505', 1),
+ (1877, 'OLIVEIRA', 11, '3145604', 1),
+ (1878, 'OLIVEIRA FORTES', 11, '3145703', 1),
+ (1879, 'ONCA DE PITANGUI', 11, '3145802', 1),
+ (1880, 'ORATORIOS', 11, '3145851', 1),
+ (1881, 'ORIZANIA', 11, '3145877', 1),
+ (1882, 'OURO BRANCO', 11, '3145901', 1),
+ (1883, 'OURO FINO', 11, '3146008', 1),
+ (1884, 'OURO PRETO', 11, '3146107', 1),
+ (1885, 'OURO VERDE DE MINAS', 11, '3146206', 1),
+ (1886, 'PADRE CARVALHO', 11, '3146255', 1),
+ (1887, 'PADRE PARAISO', 11, '3146305', 1),
+ (1888, 'PAINEIRAS', 11, '3146404', 1),
+ (1889, 'PAINS', 11, '3146503', 1),
+ (1890, 'PAI PEDRO', 11, '3146552', 1),
+ (1891, 'PAIVA', 11, '3146602', 1),
+ (1892, 'PALMA', 11, '3146701', 1),
+ (1893, 'PALMOPOLIS', 11, '3146750', 1),
+ (1894, 'PAPAGAIOS', 11, '3146909', 1),
+ (1895, 'PARACATU', 11, '3147006', 1),
+ (1896, 'PARA DE MINAS', 11, '3147105', 1),
+ (1897, 'PARAGUACU', 11, '3147204', 1),
+ (1898, 'PARAISOPOLIS', 11, '3147303', 1),
+ (1899, 'PARAOPEBA', 11, '3147402', 1),
+ (1900, 'PASSABEM', 11, '3147501', 1),
+ (1901, 'PASSA QUATRO', 11, '3147600', 1),
+ (1902, 'PASSA TEMPO', 11, '3147709', 1),
+ (1903, 'PASSA-VINTE', 11, '3147808', 1),
+ (1904, 'PASSOS', 11, '3147907', 1),
+ (1905, 'PATIS', 11, '3147956', 1),
+ (1906, 'PATOS DE MINAS', 11, '3148004', 1),
+ (1907, 'PATROCINIO', 11, '3148103', 1),
+ (1908, 'PATROCINIO DO MURIAE', 11, '3148202', 1),
+ (1909, 'PAULA CANDIDO', 11, '3148301', 1),
+ (1910, 'PAULISTAS', 11, '3148400', 1),
+ (1911, 'PAVAO', 11, '3148509', 1),
+ (1912, 'PECANHA', 11, '3148608', 1),
+ (1913, 'PEDRA AZUL', 11, '3148707', 1),
+ (1914, 'PEDRA BONITA', 11, '3148756', 1),
+ (1915, 'PEDRA DO ANTA', 11, '3148806', 1),
+ (1916, 'PEDRA DO INDAIA', 11, '3148905', 1),
+ (1917, 'PEDRA DOURADA', 11, '3149002', 1),
+ (1918, 'PEDRALVA', 11, '3149101', 1),
+ (1919, 'PEDRAS DE MARIA DA CRUZ', 11, '3149150', 1),
+ (1920, 'PEDRINOPOLIS', 11, '3149200', 1),
+ (1921, 'PEDRO LEOPOLDO', 11, '3149309', 1),
+ (1922, 'PEDRO TEIXEIRA', 11, '3149408', 1),
+ (1923, 'PEQUERI', 11, '3149507', 1),
+ (1924, 'PEQUI', 11, '3149606', 1),
+ (1925, 'PERDIGAO', 11, '3149705', 1),
+ (1926, 'PERDIZES', 11, '3149804', 1),
+ (1927, 'PERDOES', 11, '3149903', 1),
+ (1928, 'PERIQUITO', 11, '3149952', 1),
+ (1929, 'PESCADOR', 11, '3150000', 1),
+ (1930, 'PIAU', 11, '3150109', 1),
+ (1931, 'PIEDADE DE CARATINGA', 11, '3150158', 1),
+ (1932, 'PIEDADE DE PONTE NOVA', 11, '3150208', 1),
+ (1933, 'PIEDADE DO RIO GRANDE', 11, '3150307', 1),
+ (1934, 'PIEDADE DOS GERAIS', 11, '3150406', 1),
+ (1935, 'PIMENTA', 11, '3150505', 1),
+ (1936, 'PINGO-DAGUA', 11, '3150539', 1),
+ (1937, 'PINTOPOLIS', 11, '3150570', 1),
+ (1938, 'PIRACEMA', 11, '3150604', 1),
+ (1939, 'PIRAJUBA', 11, '3150703', 1),
+ (1940, 'PIRANGA', 11, '3150802', 1),
+ (1941, 'PIRANGUCU', 11, '3150901', 1),
+ (1942, 'PIRANGUINHO', 11, '3151008', 1),
+ (1943, 'PIRAPETINGA', 11, '3151107', 1),
+ (1944, 'PIRAPORA', 11, '3151206', 1),
+ (1945, 'PIRAUBA', 11, '3151305', 1),
+ (1946, 'PITANGUI', 11, '3151404', 1),
+ (1947, 'PIUMHI', 11, '3151503', 1),
+ (1948, 'PLANURA', 11, '3151602', 1),
+ (1949, 'POCO FUNDO', 11, '3151701', 1),
+ (1950, 'POCOS DE CALDAS', 11, '3151800', 1),
+ (1951, 'POCRANE', 11, '3151909', 1),
+ (1952, 'POMPEU', 11, '3152006', 1),
+ (1953, 'PONTE NOVA', 11, '3152105', 1),
+ (1954, 'PONTO CHIQUE', 11, '3152131', 1),
+ (1955, 'PONTO DOS VOLANTES', 11, '3152170', 1),
+ (1956, 'PORTEIRINHA', 11, '3152204', 1),
+ (1957, 'PORTO FIRME', 11, '3152303', 1),
+ (1958, 'POTE', 11, '3152402', 1),
+ (1959, 'POUSO ALEGRE', 11, '3152501', 1),
+ (1960, 'POUSO ALTO', 11, '3152600', 1),
+ (1961, 'PRADOS', 11, '3152709', 1),
+ (1962, 'PRATA', 11, '3152808', 1),
+ (1963, 'PRATAPOLIS', 11, '3152907', 1),
+ (1964, 'PRATINHA', 11, '3153004', 1),
+ (1965, 'PRESIDENTE BERNARDES', 11, '3153103', 1),
+ (1966, 'PRESIDENTE JUSCELINO', 11, '3153202', 1),
+ (1967, 'PRESIDENTE KUBITSCHEK', 11, '3153301', 1),
+ (1968, 'PRESIDENTE OLEGARIO', 11, '3153400', 1),
+ (1969, 'ALTO JEQUITIBA', 11, '3153509', 1),
+ (1970, 'PRUDENTE DE MORAIS', 11, '3153608', 1),
+ (1971, 'QUARTEL GERAL', 11, '3153707', 1),
+ (1972, 'QUELUZITO', 11, '3153806', 1),
+ (1973, 'RAPOSOS', 11, '3153905', 1),
+ (1974, 'RAUL SOARES', 11, '3154002', 1),
+ (1975, 'RECREIO', 11, '3154101', 1),
+ (1976, 'REDUTO', 11, '3154150', 1),
+ (1977, 'RESENDE COSTA', 11, '3154200', 1),
+ (1978, 'RESPLENDOR', 11, '3154309', 1),
+ (1979, 'RESSAQUINHA', 11, '3154408', 1),
+ (1980, 'RIACHINHO', 11, '3154457', 1),
+ (1981, 'RIACHO DOS MACHADOS', 11, '3154507', 1),
+ (1982, 'RIBEIRAO DAS NEVES', 11, '3154606', 1),
+ (1983, 'RIBEIRAO VERMELHO', 11, '3154705', 1),
+ (1984, 'RIO ACIMA', 11, '3154804', 1),
+ (1985, 'RIO CASCA', 11, '3154903', 1),
+ (1986, 'RIO DOCE', 11, '3155009', 1),
+ (1987, 'RIO DO PRADO', 11, '3155108', 1),
+ (1988, 'RIO ESPERA', 11, '3155207', 1),
+ (1989, 'RIO MANSO', 11, '3155306', 1),
+ (1990, 'RIO NOVO', 11, '3155405', 1),
+ (1991, 'RIO PARANAIBA', 11, '3155504', 1),
+ (1992, 'RIO PARDO DE MINAS', 11, '3155603', 1),
+ (1993, 'RIO PIRACICABA', 11, '3155702', 1),
+ (1994, 'RIO POMBA', 11, '3155801', 1),
+ (1995, 'RIO PRETO', 11, '3155900', 1),
+ (1996, 'RIO VERMELHO', 11, '3156007', 1),
+ (1997, 'RITAPOLIS', 11, '3156106', 1),
+ (1998, 'ROCHEDO DE MINAS', 11, '3156205', 1),
+ (1999, 'RODEIRO', 11, '3156304', 1),
+ (2000, 'ROMARIA', 11, '3156403', 1),
+ (2001, 'ROSARIO DA LIMEIRA', 11, '3156452', 1),
+ (2002, 'RUBELITA', 11, '3156502', 1),
+ (2003, 'RUBIM', 11, '3156601', 1),
+ (2004, 'SABARA', 11, '3156700', 1),
+ (2005, 'SABINOPOLIS', 11, '3156809', 1),
+ (2006, 'SACRAMENTO', 11, '3156908', 1),
+ (2007, 'SALINAS', 11, '3157005', 1),
+ (2008, 'SALTO DA DIVISA', 11, '3157104', 1),
+ (2009, 'SANTA BARBARA', 11, '3157203', 1),
+ (2010, 'SANTA BARBARA DO LESTE', 11, '3157252', 1),
+ (2011, 'SANTA BARBARA DO MONTE VERDE', 11, '3157278', 1),
+ (2012, 'SANTA BARBARA DO TUGURIO', 11, '3157302', 1),
+ (2013, 'SANTA CRUZ DE MINAS', 11, '3157336', 1),
+ (2014, 'SANTA CRUZ DE SALINAS', 11, '3157377', 1),
+ (2015, 'SANTA CRUZ DO ESCALVADO', 11, '3157401', 1),
+ (2016, 'SANTA EFIGENIA DE MINAS', 11, '3157500', 1),
+ (2017, 'SANTA FE DE MINAS', 11, '3157609', 1),
+ (2018, 'SANTA HELENA DE MINAS', 11, '3157658', 1),
+ (2019, 'SANTA JULIANA', 11, '3157708', 1),
+ (2020, 'SANTA LUZIA', 11, '3157807', 1),
+ (2021, 'SANTA MARGARIDA', 11, '3157906', 1),
+ (2022, 'SANTA MARIA DE ITABIRA', 11, '3158003', 1),
+ (2023, 'SANTA MARIA DO SALTO', 11, '3158102', 1),
+ (2024, 'SANTA MARIA DO SUACUI', 11, '3158201', 1),
+ (2025, 'SANTANA DA VARGEM', 11, '3158300', 1),
+ (2026, 'SANTANA DE CATAGUASES', 11, '3158409', 1),
+ (2027, 'SANTANA DE PIRAPAMA', 11, '3158508', 1),
+ (2028, 'SANTANA DO DESERTO', 11, '3158607', 1),
+ (2029, 'SANTANA DO GARAMBEU', 11, '3158706', 1),
+ (2030, 'SANTANA DO JACARE', 11, '3158805', 1),
+ (2031, 'SANTANA DO MANHUACU', 11, '3158904', 1),
+ (2032, 'SANTANA DO PARAISO', 11, '3158953', 1),
+ (2033, 'SANTANA DO RIACHO', 11, '3159001', 1),
+ (2034, 'SANTANA DOS MONTES', 11, '3159100', 1),
+ (2035, 'SANTA RITA DE CALDAS', 11, '3159209', 1),
+ (2036, 'SANTA RITA DE JACUTINGA', 11, '3159308', 1),
+ (2037, 'SANTA RITA DE MINAS', 11, '3159357', 1),
+ (2038, 'SANTA RITA DE IBITIPOCA', 11, '3159407', 1),
+ (2039, 'SANTA RITA DO ITUETO', 11, '3159506', 1),
+ (2040, 'SANTA RITA DO SAPUCAI', 11, '3159605', 1),
+ (2041, 'SANTA ROSA DA SERRA', 11, '3159704', 1),
+ (2042, 'SANTA VITORIA', 11, '3159803', 1),
+ (2043, 'SANTO ANTONIO DO AMPARO', 11, '3159902', 1),
+ (2044, 'SANTO ANTONIO DO AVENTUREIRO', 11, '3160009', 1),
+ (2045, 'SANTO ANTONIO DO GRAMA', 11, '3160108', 1),
+ (2046, 'SANTO ANTONIO DO ITAMBE', 11, '3160207', 1),
+ (2047, 'SANTO ANTONIO DO JACINTO', 11, '3160306', 1),
+ (2048, 'SANTO ANTONIO DO MONTE', 11, '3160405', 1),
+ (2049, 'SANTO ANTONIO DO RETIRO', 11, '3160454', 1),
+ (2050, 'SANTO ANTONIO DO RIO ABAIXO', 11, '3160504', 1),
+ (2051, 'SANTO HIPOLITO', 11, '3160603', 1),
+ (2052, 'SANTOS DUMONT', 11, '3160702', 1),
+ (2053, 'SAO BENTO ABADE', 11, '3160801', 1),
+ (2054, 'SAO BRAS DO SUACUI', 11, '3160900', 1),
+ (2055, 'SAO DOMINGOS DAS DORES', 11, '3160959', 1),
+ (2056, 'SAO DOMINGOS DO PRATA', 11, '3161007', 1),
+ (2057, 'SAO FELIX DE MINAS', 11, '3161056', 1),
+ (2058, 'SAO FRANCISCO', 11, '3161106', 1),
+ (2059, 'SAO FRANCISCO DE PAULA', 11, '3161205', 1),
+ (2060, 'SAO FRANCISCO DE SALES', 11, '3161304', 1),
+ (2061, 'SAO FRANCISCO DO GLORIA', 11, '3161403', 1),
+ (2062, 'SAO GERALDO', 11, '3161502', 1),
+ (2063, 'SAO GERALDO DA PIEDADE', 11, '3161601', 1),
+ (2064, 'SAO GERALDO DO BAIXIO', 11, '3161650', 1),
+ (2065, 'SAO GONCALO DO ABAETE', 11, '3161700', 1),
+ (2066, 'SAO GONCALO DO PARA', 11, '3161809', 1),
+ (2067, 'SAO GONCALO DO RIO ABAIXO', 11, '3161908', 1),
+ (2068, 'SAO GONCALO DO SAPUCAI', 11, '3162005', 1),
+ (2069, 'SAO GOTARDO', 11, '3162104', 1),
+ (2070, 'SAO JOAO BATISTA DO GLORIA', 11, '3162203', 1),
+ (2071, 'SAO JOAO DA LAGOA', 11, '3162252', 1),
+ (2072, 'SAO JOAO DA MATA', 11, '3162302', 1),
+ (2073, 'SAO JOAO DA PONTE', 11, '3162401', 1),
+ (2074, 'SAO JOAO DAS MISSOES', 11, '3162450', 1),
+ (2075, 'SAO JOAO DEL REI', 11, '3162500', 1),
+ (2076, 'SAO JOAO DO MANHUACU', 11, '3162559', 1),
+ (2077, 'SAO JOAO DO MANTENINHA', 11, '3162575', 1),
+ (2078, 'SAO JOAO DO ORIENTE', 11, '3162609', 1),
+ (2079, 'SAO JOAO DO PACUI', 11, '3162658', 1),
+ (2080, 'SAO JOAO DO PARAISO', 11, '3162708', 1),
+ (2081, 'SAO JOAO EVANGELISTA', 11, '3162807', 1),
+ (2082, 'SAO JOAO NEPOMUCENO', 11, '3162906', 1),
+ (2083, 'SAO JOAQUIM DE BICAS', 11, '3162922', 1),
+ (2084, 'SAO JOSE DA BARRA', 11, '3162948', 1),
+ (2085, 'SAO JOSE DA LAPA', 11, '3162955', 1),
+ (2086, 'SAO JOSE DA SAFIRA', 11, '3163003', 1),
+ (2087, 'SAO JOSE DA VARGINHA', 11, '3163102', 1),
+ (2088, 'SAO JOSE DO ALEGRE', 11, '3163201', 1),
+ (2089, 'SAO JOSE DO DIVINO', 11, '3163300', 1),
+ (2090, 'SAO JOSE DO GOIABAL', 11, '3163409', 1),
+ (2091, 'SAO JOSE DO JACURI', 11, '3163508', 1),
+ (2092, 'SAO JOSE DO MANTIMENTO', 11, '3163607', 1),
+ (2093, 'SAO LOURENCO', 11, '3163706', 1),
+ (2094, 'SAO MIGUEL DO ANTA', 11, '3163805', 1),
+ (2095, 'SAO PEDRO DA UNIAO', 11, '3163904', 1),
+ (2096, 'SAO PEDRO DOS FERROS', 11, '3164001', 1),
+ (2097, 'SAO PEDRO DO SUACUI', 11, '3164100', 1),
+ (2098, 'SAO ROMAO', 11, '3164209', 1),
+ (2099, 'SAO ROQUE DE MINAS', 11, '3164308', 1),
+ (2100, 'SAO SEBASTIAO DA BELA VISTA', 11, '3164407', 1),
+ (2101, 'SAO SEBASTIAO DA VARGEM ALEGRE', 11, '3164431', 1),
+ (2102, 'SAO SEBASTIAO DO ANTA', 11, '3164472', 1),
+ (2103, 'SAO SEBASTIAO DO MARANHAO', 11, '3164506', 1),
+ (2104, 'SAO SEBASTIAO DO OESTE', 11, '3164605', 1),
+ (2105, 'SAO SEBASTIAO DO PARAISO', 11, '3164704', 1),
+ (2106, 'SAO SEBASTIAO DO RIO PRETO', 11, '3164803', 1),
+ (2107, 'SAO SEBASTIAO DO RIO VERDE', 11, '3164902', 1),
+ (2108, 'SAO TIAGO', 11, '3165008', 1),
+ (2109, 'SAO TOMAS DE AQUINO', 11, '3165107', 1),
+ (2110, 'SAO THOME DAS LETRAS', 11, '3165206', 1),
+ (2111, 'SAO VICENTE DE MINAS', 11, '3165305', 1),
+ (2112, 'SAPUCAI-MIRIM', 11, '3165404', 1),
+ (2113, 'SARDOA', 11, '3165503', 1),
+ (2114, 'SARZEDO', 11, '3165537', 1),
+ (2115, 'SETUBINHA', 11, '3165552', 1),
+ (2116, 'SEM-PEIXE', 11, '3165560', 1),
+ (2117, 'SENADOR AMARAL', 11, '3165578', 1),
+ (2118, 'SENADOR CORTES', 11, '3165602', 1),
+ (2119, 'SENADOR FIRMINO', 11, '3165701', 1),
+ (2120, 'SENADOR JOSE BENTO', 11, '3165800', 1),
+ (2121, 'SENADOR MODESTINO GONCALVES', 11, '3165909', 1),
+ (2122, 'SENHORA DE OLIVEIRA', 11, '3166006', 1),
+ (2123, 'SENHORA DO PORTO', 11, '3166105', 1),
+ (2124, 'SENHORA DOS REMEDIOS', 11, '3166204', 1),
+ (2125, 'SERICITA', 11, '3166303', 1),
+ (2126, 'SERITINGA', 11, '3166402', 1),
+ (2127, 'SERRA AZUL DE MINAS', 11, '3166501', 1),
+ (2128, 'SERRA DA SAUDADE', 11, '3166600', 1),
+ (2129, 'SERRA DOS AIMORES', 11, '3166709', 1),
+ (2130, 'SERRA DO SALITRE', 11, '3166808', 1),
+ (2131, 'SERRANIA', 11, '3166907', 1),
+ (2132, 'SERRANOPOLIS DE MINAS', 11, '3166956', 1),
+ (2133, 'SERRANOS', 11, '3167004', 1),
+ (2134, 'SERRO', 11, '3167103', 1),
+ (2135, 'SETE LAGOAS', 11, '3167202', 1),
+ (2136, 'SILVEIRANIA', 11, '3167301', 1),
+ (2137, 'SILVIANOPOLIS', 11, '3167400', 1),
+ (2138, 'SIMAO PEREIRA', 11, '3167509', 1),
+ (2139, 'SIMONESIA', 11, '3167608', 1),
+ (2140, 'SOBRALIA', 11, '3167707', 1),
+ (2141, 'SOLEDADE DE MINAS', 11, '3167806', 1),
+ (2142, 'TABULEIRO', 11, '3167905', 1),
+ (2143, 'TAIOBEIRAS', 11, '3168002', 1),
+ (2144, 'TAPARUBA', 11, '3168051', 1),
+ (2145, 'TAPIRA', 11, '3168101', 1),
+ (2146, 'TAPIRAI', 11, '3168200', 1),
+ (2147, 'TAQUARACU DE MINAS', 11, '3168309', 1),
+ (2148, 'TARUMIRIM', 11, '3168408', 1),
+ (2149, 'TEIXEIRAS', 11, '3168507', 1),
+ (2150, 'TEOFILO OTONI', 11, '3168606', 1),
+ (2151, 'TIMOTEO', 11, '3168705', 1),
+ (2152, 'TIRADENTES', 11, '3168804', 1),
+ (2153, 'TIROS', 11, '3168903', 1),
+ (2154, 'TOCANTINS', 11, '3169000', 1),
+ (2155, 'TOCOS DO MOJI', 11, '3169059', 1),
+ (2156, 'TOLEDO', 11, '3169109', 1),
+ (2157, 'TOMBOS', 11, '3169208', 1),
+ (2158, 'TRES CORACOES', 11, '3169307', 1),
+ (2159, 'TRES MARIAS', 11, '3169356', 1),
+ (2160, 'TRES PONTAS', 11, '3169406', 1),
+ (2161, 'TUMIRITINGA', 11, '3169505', 1),
+ (2162, 'TUPACIGUARA', 11, '3169604', 1),
+ (2163, 'TURMALINA', 11, '3169703', 1),
+ (2164, 'TURVOLANDIA', 11, '3169802', 1),
+ (2165, 'UBA', 11, '3169901', 1),
+ (2166, 'UBAI', 11, '3170008', 1),
+ (2167, 'UBAPORANGA', 11, '3170057', 1),
+ (2168, 'UBERABA', 11, '3170107', 1),
+ (2169, 'UBERLANDIA', 11, '3170206', 1),
+ (2170, 'UMBURATIBA', 11, '3170305', 1),
+ (2171, 'UNAI', 11, '3170404', 1),
+ (2172, 'UNIAO DE MINAS', 11, '3170438', 1),
+ (2173, 'URUANA DE MINAS', 11, '3170479', 1),
+ (2174, 'URUCANIA', 11, '3170503', 1),
+ (2175, 'URUCUIA', 11, '3170529', 1),
+ (2176, 'VARGEM ALEGRE', 11, '3170578', 1),
+ (2177, 'VARGEM BONITA', 11, '3170602', 1),
+ (2178, 'VARGEM GRANDE DO RIO PARDO', 11, '3170651', 1),
+ (2179, 'VARGINHA', 11, '3170701', 1),
+ (2180, 'VARJAO DE MINAS', 11, '3170750', 1),
+ (2181, 'VARZEA DA PALMA', 11, '3170800', 1),
+ (2182, 'VARZELANDIA', 11, '3170909', 1),
+ (2183, 'VAZANTE', 11, '3171006', 1),
+ (2184, 'VERDELANDIA', 11, '3171030', 1),
+ (2185, 'VEREDINHA', 11, '3171071', 1),
+ (2186, 'VERISSIMO', 11, '3171105', 1),
+ (2187, 'VERMELHO NOVO', 11, '3171154', 1),
+ (2188, 'VESPASIANO', 11, '3171204', 1),
+ (2189, 'VICOSA', 11, '3171303', 1),
+ (2190, 'VIEIRAS', 11, '3171402', 1),
+ (2191, 'MATHIAS LOBATO', 11, '3171501', 1),
+ (2192, 'VIRGEM DA LAPA', 11, '3171600', 1),
+ (2193, 'VIRGINIA', 11, '3171709', 1),
+ (2194, 'VIRGINOPOLIS', 11, '3171808', 1),
+ (2195, 'VIRGOLANDIA', 11, '3171907', 1),
+ (2196, 'VISCONDE DO RIO BRANCO', 11, '3172004', 1),
+ (2197, 'VOLTA GRANDE', 11, '3172103', 1),
+ (2198, 'WENCESLAU BRAZ', 11, '3172202', 1),
+ (2199, 'AGUA CLARA', 12, '5000203', 1),
+ (2200, 'ALCINOPOLIS', 12, '5000252', 1),
+ (2201, 'AMAMBAI', 12, '5000609', 1),
+ (2202, 'ANASTACIO', 12, '5000708', 1),
+ (2203, 'ANAURILANDIA', 12, '5000807', 1),
+ (2204, 'ANGELICA', 12, '5000856', 1),
+ (2205, 'ANTONIO JOAO', 12, '5000906', 1),
+ (2206, 'APARECIDA DO TABOADO', 12, '5001003', 1),
+ (2207, 'AQUIDAUANA', 12, '5001102', 1),
+ (2208, 'ARAL MOREIRA', 12, '5001243', 1),
+ (2209, 'BANDEIRANTES', 12, '5001508', 1),
+ (2210, 'BATAGUASSU', 12, '5001904', 1),
+ (2211, 'BATAYPORA', 12, '5002001', 1),
+ (2212, 'BELA VISTA', 12, '5002100', 1),
+ (2213, 'BODOQUENA', 12, '5002159', 1),
+ (2214, 'BONITO', 12, '5002209', 1),
+ (2215, 'BRASILANDIA', 12, '5002308', 1),
+ (2216, 'CAARAPO', 12, '5002407', 1),
+ (2217, 'CAMAPUA', 12, '5002605', 1),
+ (2218, 'CAMPO GRANDE', 12, '5002704', 1),
+ (2219, 'CARACOL', 12, '5002803', 1),
+ (2220, 'CASSILANDIA', 12, '5002902', 1),
+ (2221, 'CHAPADAO DO SUL', 12, '5002951', 1),
+ (2222, 'CORGUINHO', 12, '5003108', 1),
+ (2223, 'CORONEL SAPUCAIA', 12, '5003157', 1),
+ (2224, 'CORUMBA', 12, '5003207', 1),
+ (2225, 'COSTA RICA', 12, '5003256', 1),
+ (2226, 'COXIM', 12, '5003306', 1),
+ (2227, 'DEODAPOLIS', 12, '5003454', 1),
+ (2228, 'DOIS IRMAOS DO BURITI', 12, '5003488', 1),
+ (2229, 'DOURADINA', 12, '5003504', 1),
+ (2230, 'DOURADOS', 12, '5003702', 1),
+ (2231, 'ELDORADO', 12, '5003751', 1),
+ (2232, 'FATIMA DO SUL', 12, '5003801', 1),
+ (2233, 'FIGUEIRAO', 12, '5003900', 1),
+ (2234, 'GLORIA DE DOURADOS', 12, '5004007', 1),
+ (2235, 'GUIA LOPES DA LAGUNA', 12, '5004106', 1),
+ (2236, 'IGUATEMI', 12, '5004304', 1),
+ (2237, 'INOCENCIA', 12, '5004403', 1),
+ (2238, 'ITAPORA', 12, '5004502', 1),
+ (2239, 'ITAQUIRAI', 12, '5004601', 1),
+ (2240, 'IVINHEMA', 12, '5004700', 1),
+ (2241, 'JAPORA', 12, '5004809', 1),
+ (2242, 'JARAGUARI', 12, '5004908', 1),
+ (2243, 'JARDIM', 12, '5005004', 1),
+ (2244, 'JATEI', 12, '5005103', 1),
+ (2245, 'JUTI', 12, '5005152', 1),
+ (2246, 'LADARIO', 12, '5005202', 1),
+ (2247, 'LAGUNA CARAPA', 12, '5005251', 1),
+ (2248, 'MARACAJU', 12, '5005400', 1),
+ (2249, 'MIRANDA', 12, '5005608', 1),
+ (2250, 'MUNDO NOVO', 12, '5005681', 1),
+ (2251, 'NAVIRAI', 12, '5005707', 1),
+ (2252, 'NIOAQUE', 12, '5005806', 1),
+ (2253, 'NOVA ALVORADA DO SUL', 12, '5006002', 1),
+ (2254, 'NOVA ANDRADINA', 12, '5006200', 1),
+ (2255, 'NOVO HORIZONTE DO SUL', 12, '5006259', 1),
+ (2256, 'PARANAIBA', 12, '5006309', 1),
+ (2257, 'PARANHOS', 12, '5006358', 1),
+ (2258, 'PEDRO GOMES', 12, '5006408', 1),
+ (2259, 'PONTA PORA', 12, '5006606', 1),
+ (2260, 'PORTO MURTINHO', 12, '5006903', 1),
+ (2261, 'RIBAS DO RIO PARDO', 12, '5007109', 1),
+ (2262, 'RIO BRILHANTE', 12, '5007208', 1),
+ (2263, 'RIO NEGRO', 12, '5007307', 1),
+ (2264, 'RIO VERDE DE MATO GROSSO', 12, '5007406', 1),
+ (2265, 'ROCHEDO', 12, '5007505', 1),
+ (2266, 'SANTA RITA DO PARDO', 12, '5007554', 1),
+ (2267, 'SAO GABRIEL DO OESTE', 12, '5007695', 1),
+ (2268, 'SETE QUEDAS', 12, '5007703', 1),
+ (2269, 'SELVIRIA', 12, '5007802', 1),
+ (2270, 'SIDROLANDIA', 12, '5007901', 1),
+ (2271, 'SONORA', 12, '5007935', 1),
+ (2272, 'TACURU', 12, '5007950', 1),
+ (2273, 'TAQUARUSSU', 12, '5007976', 1),
+ (2274, 'TERENOS', 12, '5008008', 1),
+ (2275, 'TRES LAGOAS', 12, '5008305', 1),
+ (2276, 'VICENTINA', 12, '5008404', 1),
+ (2277, 'ACORIZAL', 13, '5100102', 1),
+ (2278, 'AGUA BOA', 13, '5100201', 1),
+ (2279, 'ALTA FLORESTA', 13, '5100250', 1),
+ (2280, 'ALTO ARAGUAIA', 13, '5100300', 1),
+ (2281, 'ALTO BOA VISTA', 13, '5100359', 1),
+ (2282, 'ALTO GARCAS', 13, '5100409', 1),
+ (2283, 'ALTO PARAGUAI', 13, '5100508', 1),
+ (2284, 'ALTO TAQUARI', 13, '5100607', 1),
+ (2285, 'APIACAS', 13, '5100805', 1),
+ (2286, 'ARAGUAIANA', 13, '5101001', 1),
+ (2287, 'ARAGUAINHA', 13, '5101209', 1),
+ (2288, 'ARAPUTANGA', 13, '5101258', 1),
+ (2289, 'ARENAPOLIS', 13, '5101308', 1),
+ (2290, 'ARIPUANA', 13, '5101407', 1),
+ (2291, 'BARAO DE MELGACO', 13, '5101605', 1),
+ (2292, 'BARRA DO BUGRES', 13, '5101704', 1),
+ (2293, 'BARRA DO GARCAS', 13, '5101803', 1),
+ (2294, 'BOM JESUS DO ARAGUAIA', 13, '5101852', 1),
+ (2295, 'BRASNORTE', 13, '5101902', 1),
+ (2296, 'CACERES', 13, '5102504', 1),
+ (2297, 'CAMPINAPOLIS', 13, '5102603', 1),
+ (2298, 'CAMPO NOVO DO PARECIS', 13, '5102637', 1),
+ (2299, 'CAMPO VERDE', 13, '5102678', 1),
+ (2300, 'CAMPOS DE JULIO', 13, '5102686', 1),
+ (2301, 'CANABRAVA DO NORTE', 13, '5102694', 1),
+ (2302, 'CANARANA', 13, '5102702', 1),
+ (2303, 'CARLINDA', 13, '5102793', 1),
+ (2304, 'CASTANHEIRA', 13, '5102850', 1),
+ (2305, 'CHAPADA DOS GUIMARAES', 13, '5103007', 1),
+ (2306, 'CLAUDIA', 13, '5103056', 1),
+ (2307, 'COCALINHO', 13, '5103106', 1),
+ (2308, 'COLIDER', 13, '5103205', 1),
+ (2309, 'COLNIZA', 13, '5103254', 1),
+ (2310, 'COMODORO', 13, '5103304', 1),
+ (2311, 'CONFRESA', 13, '5103353', 1),
+ (2312, 'CONQUISTA DOESTE', 13, '5103361', 1),
+ (2313, 'COTRIGUACU', 13, '5103379', 1),
+ (2314, 'CUIABA', 13, '5103403', 1),
+ (2315, 'CURVELANDIA', 13, '5103437', 1),
+ (2316, 'DENISE', 13, '5103452', 1),
+ (2317, 'DIAMANTINO', 13, '5103502', 1),
+ (2318, 'DOM AQUINO', 13, '5103601', 1),
+ (2319, 'FELIZ NATAL', 13, '5103700', 1),
+ (2320, 'FIGUEIROPOLIS DOESTE', 13, '5103809', 1),
+ (2321, 'GAUCHA DO NORTE', 13, '5103858', 1),
+ (2322, 'GENERAL CARNEIRO', 13, '5103908', 1),
+ (2323, 'GLORIA DOESTE', 13, '5103957', 1),
+ (2324, 'GUARANTA DO NORTE', 13, '5104104', 1),
+ (2325, 'GUIRATINGA', 13, '5104203', 1),
+ (2326, 'INDIAVAI', 13, '5104500', 1),
+ (2327, 'IPIRANGA DO NORTE', 13, '5104526', 1),
+ (2328, 'ITANHANGA', 13, '5104542', 1),
+ (2329, 'BOILERPLATEBA', 13, '5104559', 1),
+ (2330, 'ITIQUIRA', 13, '5104609', 1),
+ (2331, 'JACIARA', 13, '5104807', 1),
+ (2332, 'JANGADA', 13, '5104906', 1),
+ (2333, 'JAURU', 13, '5105002', 1),
+ (2334, 'JUARA', 13, '5105101', 1),
+ (2335, 'JUINA', 13, '5105150', 1),
+ (2336, 'JURUENA', 13, '5105176', 1),
+ (2337, 'JUSCIMEIRA', 13, '5105200', 1),
+ (2338, 'LAMBARI DOESTE', 13, '5105234', 1),
+ (2339, 'LUCAS DO RIO VERDE', 13, '5105259', 1),
+ (2340, 'LUCIARA', 13, '5105309', 1),
+ (2341, 'VILA BELA DA SANTISSIMA TRINDADE', 13, '5105507', 1),
+ (2342, 'MARCELANDIA', 13, '5105580', 1),
+ (2343, 'MATUPA', 13, '5105606', 1),
+ (2344, 'MIRASSOL DOESTE', 13, '5105622', 1),
+ (2345, 'NOBRES', 13, '5105903', 1),
+ (2346, 'NORTELANDIA', 13, '5106000', 1),
+ (2347, 'NOSSA SENHORA DO LIVRAMENTO', 13, '5106109', 1),
+ (2348, 'NOVA BANDEIRANTES', 13, '5106158', 1),
+ (2349, 'NOVA NAZARE', 13, '5106174', 1),
+ (2350, 'NOVA LACERDA', 13, '5106182', 1),
+ (2351, 'NOVA SANTA HELENA', 13, '5106190', 1),
+ (2352, 'NOVA BRASILANDIA', 13, '5106208', 1),
+ (2353, 'NOVA CANAA DO NORTE', 13, '5106216', 1),
+ (2354, 'NOVA MUTUM', 13, '5106224', 1),
+ (2355, 'NOVA OLIMPIA', 13, '5106232', 1),
+ (2356, 'NOVA UBIRATA', 13, '5106240', 1),
+ (2357, 'NOVA XAVANTINA', 13, '5106257', 1),
+ (2358, 'NOVO MUNDO', 13, '5106265', 1),
+ (2359, 'NOVO HORIZONTE DO NORTE', 13, '5106273', 1),
+ (2360, 'NOVO SAO JOAQUIM', 13, '5106281', 1),
+ (2361, 'PARANAITA', 13, '5106299', 1),
+ (2362, 'PARANATINGA', 13, '5106307', 1),
+ (2363, 'NOVO SANTO ANTONIO', 13, '5106315', 1),
+ (2364, 'PEDRA PRETA', 13, '5106372', 1),
+ (2365, 'PEIXOTO DE AZEVEDO', 13, '5106422', 1),
+ (2366, 'PLANALTO DA SERRA', 13, '5106455', 1),
+ (2367, 'POCONE', 13, '5106505', 1),
+ (2368, 'PONTAL DO ARAGUAIA', 13, '5106653', 1),
+ (2369, 'PONTE BRANCA', 13, '5106703', 1),
+ (2370, 'PONTES E LACERDA', 13, '5106752', 1),
+ (2371, 'PORTO ALEGRE DO NORTE', 13, '5106778', 1),
+ (2372, 'PORTO DOS GAUCHOS', 13, '5106802', 1),
+ (2373, 'PORTO ESPERIDIAO', 13, '5106828', 1),
+ (2374, 'PORTO ESTRELA', 13, '5106851', 1),
+ (2375, 'POXOREO', 13, '5107008', 1),
+ (2376, 'PRIMAVERA DO LESTE', 13, '5107040', 1),
+ (2377, 'QUERENCIA', 13, '5107065', 1),
+ (2378, 'SAO JOSE DOS QUATRO MARCOS', 13, '5107107', 1),
+ (2379, 'RESERVA DO CABACAL', 13, '5107156', 1),
+ (2380, 'RIBEIRAO CASCALHEIRA', 13, '5107180', 1),
+ (2381, 'RIBEIRAOZINHO', 13, '5107198', 1),
+ (2382, 'RIO BRANCO', 13, '5107206', 1),
+ (2383, 'SANTA CARMEM', 13, '5107248', 1),
+ (2384, 'SANTO AFONSO', 13, '5107263', 1),
+ (2385, 'SAO JOSE DO POVO', 13, '5107297', 1),
+ (2386, 'SAO JOSE DO RIO CLARO', 13, '5107305', 1),
+ (2387, 'SAO JOSE DO XINGU', 13, '5107354', 1),
+ (2388, 'SAO PEDRO DA CIPA', 13, '5107404', 1),
+ (2389, 'RONDOLANDIA', 13, '5107578', 1),
+ (2390, 'RONDONOPOLIS', 13, '5107602', 1),
+ (2391, 'ROSARIO OESTE', 13, '5107701', 1),
+ (2392, 'SANTA CRUZ DO XINGU', 13, '5107743', 1),
+ (2393, 'SALTO DO CEU', 13, '5107750', 1),
+ (2394, 'SANTA RITA DO TRIVELATO', 13, '5107768', 1),
+ (2395, 'SANTA TEREZINHA', 13, '5107776', 1),
+ (2396, 'SANTO ANTONIO DO LESTE', 13, '5107792', 1),
+ (2397, 'SANTO ANTONIO DO LEVERGER', 13, '5107800', 1),
+ (2398, 'SAO FELIX DO ARAGUAIA', 13, '5107859', 1),
+ (2399, 'SAPEZAL', 13, '5107875', 1),
+ (2400, 'SERRA NOVA DOURADA', 13, '5107883', 1),
+ (2401, 'SINOP', 13, '5107909', 1),
+ (2402, 'SORRISO', 13, '5107925', 1),
+ (2403, 'TABAPORA', 13, '5107941', 1),
+ (2404, 'TANGARA DA SERRA', 13, '5107958', 1),
+ (2405, 'TAPURAH', 13, '5108006', 1),
+ (2406, 'TERRA NOVA DO NORTE', 13, '5108055', 1),
+ (2407, 'TESOURO', 13, '5108105', 1),
+ (2408, 'TORIXOREU', 13, '5108204', 1),
+ (2409, 'UNIAO DO SUL', 13, '5108303', 1),
+ (2410, 'VALE DE SAO DOMINGOS', 13, '5108352', 1),
+ (2411, 'VARZEA GRANDE', 13, '5108402', 1),
+ (2412, 'VERA', 13, '5108501', 1),
+ (2413, 'VILA RICA', 13, '5108600', 1),
+ (2414, 'NOVA GUARITA', 13, '5108808', 1),
+ (2415, 'NOVA MARILANDIA', 13, '5108857', 1),
+ (2416, 'NOVA MARINGA', 13, '5108907', 1),
+ (2417, 'NOVA MONTE VERDE', 13, '5108956', 1),
+ (2418, 'ABAETETUBA', 14, '1500107', 1),
+ (2419, 'ABEL FIGUEIREDO', 14, '1500131', 1),
+ (2420, 'ACARA', 14, '1500206', 1),
+ (2421, 'AFUA', 14, '1500305', 1),
+ (2422, 'AGUA AZUL DO NORTE', 14, '1500347', 1),
+ (2423, 'ALENQUER', 14, '1500404', 1),
+ (2424, 'ALMEIRIM', 14, '1500503', 1),
+ (2425, 'ALTAMIRA', 14, '1500602', 1),
+ (2426, 'ANAJAS', 14, '1500701', 1),
+ (2427, 'ANANINDEUA', 14, '1500800', 1),
+ (2428, 'ANAPU', 14, '1500859', 1),
+ (2429, 'AUGUSTO CORREA', 14, '1500909', 1),
+ (2430, 'AURORA DO PARA', 14, '1500958', 1),
+ (2431, 'AVEIRO', 14, '1501006', 1),
+ (2432, 'BAGRE', 14, '1501105', 1),
+ (2433, 'BAIAO', 14, '1501204', 1),
+ (2434, 'BANNACH', 14, '1501253', 1),
+ (2435, 'BARCARENA', 14, '1501303', 1),
+ (2436, 'BELEM', 14, '1501402', 1),
+ (2437, 'BELTERRA', 14, '1501451', 1),
+ (2438, 'BENEVIDES', 14, '1501501', 1),
+ (2439, 'BOM JESUS DO TOCANTINS', 14, '1501576', 1),
+ (2440, 'BONITO', 14, '1501600', 1),
+ (2441, 'BRAGANCA', 14, '1501709', 1),
+ (2442, 'BRASIL NOVO', 14, '1501725', 1),
+ (2443, 'BREJO GRANDE DO ARAGUAIA', 14, '1501758', 1),
+ (2444, 'BREU BRANCO', 14, '1501782', 1),
+ (2445, 'BREVES', 14, '1501808', 1),
+ (2446, 'BUJARU', 14, '1501907', 1),
+ (2447, 'CACHOEIRA DO PIRIA', 14, '1501956', 1),
+ (2448, 'CACHOEIRA DO ARARI', 14, '1502004', 1),
+ (2449, 'CAMETA', 14, '1502103', 1),
+ (2450, 'CANAA DOS CARAJAS', 14, '1502152', 1),
+ (2451, 'CAPANEMA', 14, '1502202', 1),
+ (2452, 'CAPITAO POCO', 14, '1502301', 1),
+ (2453, 'CASTANHAL', 14, '1502400', 1),
+ (2454, 'CHAVES', 14, '1502509', 1),
+ (2455, 'COLARES', 14, '1502608', 1),
+ (2456, 'CONCEICAO DO ARAGUAIA', 14, '1502707', 1),
+ (2457, 'CONCORDIA DO PARA', 14, '1502756', 1),
+ (2458, 'CUMARU DO NORTE', 14, '1502764', 1),
+ (2459, 'CURIONOPOLIS', 14, '1502772', 1),
+ (2460, 'CURRALINHO', 14, '1502806', 1),
+ (2461, 'CURUA', 14, '1502855', 1),
+ (2462, 'CURUCA', 14, '1502905', 1),
+ (2463, 'DOM ELISEU', 14, '1502939', 1),
+ (2464, 'ELDORADO DOS CARAJAS', 14, '1502954', 1),
+ (2465, 'FARO', 14, '1503002', 1),
+ (2466, 'FLORESTA DO ARAGUAIA', 14, '1503044', 1),
+ (2467, 'GARRAFAO DO NORTE', 14, '1503077', 1),
+ (2468, 'GOIANESIA DO PARA', 14, '1503093', 1),
+ (2469, 'GURUPA', 14, '1503101', 1),
+ (2470, 'IGARAPE-ACU', 14, '1503200', 1),
+ (2471, 'IGARAPE-MIRI', 14, '1503309', 1),
+ (2472, 'INHANGAPI', 14, '1503408', 1),
+ (2473, 'IPIXUNA DO PARA', 14, '1503457', 1),
+ (2474, 'IRITUIA', 14, '1503507', 1),
+ (2475, 'ITAITUBA', 14, '1503606', 1),
+ (2476, 'ITUPIRANGA', 14, '1503705', 1),
+ (2477, 'JACAREACANGA', 14, '1503754', 1),
+ (2478, 'JACUNDA', 14, '1503804', 1),
+ (2479, 'JURUTI', 14, '1503903', 1),
+ (2480, 'LIMOEIRO DO AJURU', 14, '1504000', 1),
+ (2481, 'MAE DO RIO', 14, '1504059', 1),
+ (2482, 'MAGALHAES BARATA', 14, '1504109', 1),
+ (2483, 'MARABA', 14, '1504208', 1),
+ (2484, 'MARACANA', 14, '1504307', 1),
+ (2485, 'MARAPANIM', 14, '1504406', 1),
+ (2486, 'MARITUBA', 14, '1504422', 1),
+ (2487, 'MEDICILANDIA', 14, '1504455', 1),
+ (2488, 'MELGACO', 14, '1504505', 1),
+ (2489, 'MOCAJUBA', 14, '1504604', 1),
+ (2490, 'MOJU', 14, '1504703', 1),
+ (2491, 'MONTE ALEGRE', 14, '1504802', 1),
+ (2492, 'MUANA', 14, '1504901', 1),
+ (2493, 'NOVA ESPERANCA DO PIRIA', 14, '1504950', 1),
+ (2494, 'NOVA IPIXUNA', 14, '1504976', 1),
+ (2495, 'NOVA TIMBOTEUA', 14, '1505007', 1),
+ (2496, 'NOVO PROGRESSO', 14, '1505031', 1),
+ (2497, 'NOVO REPARTIMENTO', 14, '1505064', 1),
+ (2498, 'OBIDOS', 14, '1505106', 1),
+ (2499, 'OEIRAS DO PARA', 14, '1505205', 1),
+ (2500, 'ORIXIMINA', 14, '1505304', 1),
+ (2501, 'OUREM', 14, '1505403', 1),
+ (2502, 'OURILANDIA DO NORTE', 14, '1505437', 1),
+ (2503, 'PACAJA', 14, '1505486', 1),
+ (2504, 'PALESTINA DO PARA', 14, '1505494', 1),
+ (2505, 'PARAGOMINAS', 14, '1505502', 1),
+ (2506, 'PARAUAPEBAS', 14, '1505536', 1),
+ (2507, 'PAU DARCO', 14, '1505551', 1),
+ (2508, 'PEIXE-BOI', 14, '1505601', 1),
+ (2509, 'PICARRA', 14, '1505635', 1),
+ (2510, 'PLACAS', 14, '1505650', 1),
+ (2511, 'PONTA DE PEDRAS', 14, '1505700', 1),
+ (2512, 'PORTEL', 14, '1505809', 1),
+ (2513, 'PORTO DE MOZ', 14, '1505908', 1),
+ (2514, 'PRAINHA', 14, '1506005', 1),
+ (2515, 'PRIMAVERA', 14, '1506104', 1),
+ (2516, 'QUATIPURU', 14, '1506112', 1),
+ (2517, 'REDENCAO', 14, '1506138', 1),
+ (2518, 'RIO MARIA', 14, '1506161', 1),
+ (2519, 'RONDON DO PARA', 14, '1506187', 1),
+ (2520, 'RUROPOLIS', 14, '1506195', 1),
+ (2521, 'SALINOPOLIS', 14, '1506203', 1),
+ (2522, 'SALVATERRA', 14, '1506302', 1),
+ (2523, 'SANTA BARBARA DO PARA', 14, '1506351', 1),
+ (2524, 'SANTA CRUZ DO ARARI', 14, '1506401', 1),
+ (2525, 'SANTA ISABEL DO PARA', 14, '1506500', 1),
+ (2526, 'SANTA LUZIA DO PARA', 14, '1506559', 1),
+ (2527, 'SANTA MARIA DAS BARREIRAS', 14, '1506583', 1),
+ (2528, 'SANTA MARIA DO PARA', 14, '1506609', 1),
+ (2529, 'SANTANA DO ARAGUAIA', 14, '1506708', 1),
+ (2530, 'SANTAREM', 14, '1506807', 1),
+ (2531, 'SANTAREM NOVO', 14, '1506906', 1),
+ (2532, 'SANTO ANTONIO DO TAUA', 14, '1507003', 1),
+ (2533, 'SAO CAETANO DE ODIVELAS', 14, '1507102', 1),
+ (2534, 'SAO DOMINGOS DO ARAGUAIA', 14, '1507151', 1),
+ (2535, 'SAO DOMINGOS DO CAPIM', 14, '1507201', 1),
+ (2536, 'SAO FELIX DO XINGU', 14, '1507300', 1),
+ (2537, 'SAO FRANCISCO DO PARA', 14, '1507409', 1),
+ (2538, 'SAO GERALDO DO ARAGUAIA', 14, '1507458', 1),
+ (2539, 'SAO JOAO DA PONTA', 14, '1507466', 1),
+ (2540, 'SAO JOAO DE PIRABAS', 14, '1507474', 1),
+ (2541, 'SAO JOAO DO ARAGUAIA', 14, '1507508', 1),
+ (2542, 'SAO MIGUEL DO GUAMA', 14, '1507607', 1),
+ (2543, 'SAO SEBASTIAO DA BOA VISTA', 14, '1507706', 1),
+ (2544, 'SAPUCAIA', 14, '1507755', 1),
+ (2545, 'SENADOR JOSE PORFIRIO', 14, '1507805', 1),
+ (2546, 'SOURE', 14, '1507904', 1),
+ (2547, 'TAILANDIA', 14, '1507953', 1),
+ (2548, 'TERRA ALTA', 14, '1507961', 1),
+ (2549, 'TERRA SANTA', 14, '1507979', 1),
+ (2550, 'TOME-ACU', 14, '1508001', 1),
+ (2551, 'TRACUATEUA', 14, '1508035', 1),
+ (2552, 'TRAIRAO', 14, '1508050', 1),
+ (2553, 'TUCUMA', 14, '1508084', 1),
+ (2554, 'TUCURUI', 14, '1508100', 1),
+ (2555, 'ULIANOPOLIS', 14, '1508126', 1),
+ (2556, 'URUARA', 14, '1508159', 1),
+ (2557, 'VIGIA', 14, '1508209', 1),
+ (2558, 'VISEU', 14, '1508308', 1),
+ (2559, 'VITORIA DO XINGU', 14, '1508357', 1),
+ (2560, 'XINGUARA', 14, '1508407', 1),
+ (2561, 'AGUA BRANCA', 15, '2500106', 1),
+ (2562, 'AGUIAR', 15, '2500205', 1),
+ (2563, 'ALAGOA GRANDE', 15, '2500304', 1),
+ (2564, 'ALAGOA NOVA', 15, '2500403', 1),
+ (2565, 'ALAGOINHA', 15, '2500502', 1),
+ (2566, 'ALCANTIL', 15, '2500536', 1),
+ (2567, 'ALGODAO DE JANDAIRA', 15, '2500577', 1),
+ (2568, 'ALHANDRA', 15, '2500601', 1),
+ (2569, 'SAO JOAO DO RIO DO PEIXE', 15, '2500700', 1),
+ (2570, 'AMPARO', 15, '2500734', 1),
+ (2571, 'APARECIDA', 15, '2500775', 1),
+ (2572, 'ARACAGI', 15, '2500809', 1),
+ (2573, 'ARARA', 15, '2500908', 1),
+ (2574, 'ARARUNA', 15, '2501005', 1),
+ (2575, 'AREIA', 15, '2501104', 1),
+ (2576, 'AREIA DE BARAUNAS', 15, '2501153', 1),
+ (2577, 'AREIAL', 15, '2501203', 1),
+ (2578, 'AROEIRAS', 15, '2501302', 1),
+ (2579, 'ASSUNCAO', 15, '2501351', 1),
+ (2580, 'BAIA DA TRAICAO', 15, '2501401', 1),
+ (2581, 'BANANEIRAS', 15, '2501500', 1),
+ (2582, 'BARAUNA', 15, '2501534', 1),
+ (2583, 'BARRA DE SANTANA', 15, '2501575', 1),
+ (2584, 'BARRA DE SANTA ROSA', 15, '2501609', 1),
+ (2585, 'BARRA DE SAO MIGUEL', 15, '2501708', 1),
+ (2586, 'BAYEUX', 15, '2501807', 1),
+ (2587, 'BELEM', 15, '2501906', 1),
+ (2588, 'BELEM DO BREJO DO CRUZ', 15, '2502003', 1),
+ (2589, 'BERNARDINO BATISTA', 15, '2502052', 1),
+ (2590, 'BOA VENTURA', 15, '2502102', 1),
+ (2591, 'BOA VISTA', 15, '2502151', 1),
+ (2592, 'BOM JESUS', 15, '2502201', 1),
+ (2593, 'BOM SUCESSO', 15, '2502300', 1),
+ (2594, 'BONITO DE SANTA FE', 15, '2502409', 1),
+ (2595, 'BOQUEIRAO', 15, '2502508', 1),
+ (2596, 'IGARACY', 15, '2502607', 1),
+ (2597, 'BORBOREMA', 15, '2502706', 1),
+ (2598, 'BREJO DO CRUZ', 15, '2502805', 1),
+ (2599, 'BREJO DOS SANTOS', 15, '2502904', 1),
+ (2600, 'CAAPORA', 15, '2503001', 1),
+ (2601, 'CABACEIRAS', 15, '2503100', 1),
+ (2602, 'CABEDELO', 15, '2503209', 1),
+ (2603, 'CACHOEIRA DOS INDIOS', 15, '2503308', 1),
+ (2604, 'CACIMBA DE AREIA', 15, '2503407', 1),
+ (2605, 'CACIMBA DE DENTRO', 15, '2503506', 1),
+ (2606, 'CACIMBAS', 15, '2503555', 1),
+ (2607, 'CAICARA', 15, '2503605', 1),
+ (2608, 'CAJAZEIRAS', 15, '2503704', 1),
+ (2609, 'CAJAZEIRINHAS', 15, '2503753', 1),
+ (2610, 'CALDAS BRANDAO', 15, '2503803', 1),
+ (2611, 'CAMALAU', 15, '2503902', 1),
+ (2612, 'CAMPINA GRANDE', 15, '2504009', 1),
+ (2613, 'CAPIM', 15, '2504033', 1),
+ (2614, 'CARAUBAS', 15, '2504074', 1),
+ (2615, 'CARRAPATEIRA', 15, '2504108', 1),
+ (2616, 'CASSERENGUE', 15, '2504157', 1),
+ (2617, 'CATINGUEIRA', 15, '2504207', 1),
+ (2618, 'CATOLE DO ROCHA', 15, '2504306', 1),
+ (2619, 'CATURITE', 15, '2504355', 1),
+ (2620, 'CONCEICAO', 15, '2504405', 1),
+ (2621, 'CONDADO', 15, '2504504', 1),
+ (2622, 'CONDE', 15, '2504603', 1),
+ (2623, 'CONGO', 15, '2504702', 1),
+ (2624, 'COREMAS', 15, '2504801', 1),
+ (2625, 'COXIXOLA', 15, '2504850', 1),
+ (2626, 'CRUZ DO ESPIRITO SANTO', 15, '2504900', 1),
+ (2627, 'CUBATI', 15, '2505006', 1),
+ (2628, 'CUITE', 15, '2505105', 1),
+ (2629, 'CUITEGI', 15, '2505204', 1),
+ (2630, 'CUITE DE MAMANGUAPE', 15, '2505238', 1),
+ (2631, 'CURRAL DE CIMA', 15, '2505279', 1),
+ (2632, 'CURRAL VELHO', 15, '2505303', 1),
+ (2633, 'DAMIAO', 15, '2505352', 1),
+ (2634, 'DESTERRO', 15, '2505402', 1),
+ (2635, 'VISTA SERRANA', 15, '2505501', 1),
+ (2636, 'DIAMANTE', 15, '2505600', 1),
+ (2637, 'DONA INES', 15, '2505709', 1),
+ (2638, 'DUAS ESTRADAS', 15, '2505808', 1),
+ (2639, 'EMAS', 15, '2505907', 1),
+ (2640, 'ESPERANCA', 15, '2506004', 1),
+ (2641, 'FAGUNDES', 15, '2506103', 1),
+ (2642, 'FREI MARTINHO', 15, '2506202', 1),
+ (2643, 'GADO BRAVO', 15, '2506251', 1),
+ (2644, 'GUARABIRA', 15, '2506301', 1),
+ (2645, 'GURINHEM', 15, '2506400', 1),
+ (2646, 'GURJAO', 15, '2506509', 1),
+ (2647, 'IBIARA', 15, '2506608', 1),
+ (2648, 'IMACULADA', 15, '2506707', 1),
+ (2649, 'INGA', 15, '2506806', 1),
+ (2650, 'ITABAIANA', 15, '2506905', 1),
+ (2651, 'ITAPORANGA', 15, '2507002', 1),
+ (2652, 'ITAPOROROCA', 15, '2507101', 1),
+ (2653, 'ITATUBA', 15, '2507200', 1),
+ (2654, 'JACARAU', 15, '2507309', 1),
+ (2655, 'JERICO', 15, '2507408', 1),
+ (2656, 'JOAO PESSOA', 15, '2507507', 1),
+ (2657, 'JUAREZ TAVORA', 15, '2507606', 1),
+ (2658, 'JUAZEIRINHO', 15, '2507705', 1),
+ (2659, 'JUNCO DO SERIDO', 15, '2507804', 1),
+ (2660, 'JURIPIRANGA', 15, '2507903', 1),
+ (2661, 'JURU', 15, '2508000', 1),
+ (2662, 'LAGOA', 15, '2508109', 1),
+ (2663, 'LAGOA DE DENTRO', 15, '2508208', 1),
+ (2664, 'LAGOA SECA', 15, '2508307', 1),
+ (2665, 'LASTRO', 15, '2508406', 1),
+ (2666, 'LIVRAMENTO', 15, '2508505', 1),
+ (2667, 'LOGRADOURO', 15, '2508554', 1),
+ (2668, 'LUCENA', 15, '2508604', 1),
+ (2669, 'MAE DAGUA', 15, '2508703', 1),
+ (2670, 'MALTA', 15, '2508802', 1),
+ (2671, 'MAMANGUAPE', 15, '2508901', 1),
+ (2672, 'MANAIRA', 15, '2509008', 1),
+ (2673, 'MARCACAO', 15, '2509057', 1),
+ (2674, 'MARI', 15, '2509107', 1),
+ (2675, 'MARIZOPOLIS', 15, '2509156', 1),
+ (2676, 'MASSARANDUBA', 15, '2509206', 1),
+ (2677, 'MATARACA', 15, '2509305', 1),
+ (2678, 'MATINHAS', 15, '2509339', 1),
+ (2679, 'MATO GROSSO', 15, '2509370', 1),
+ (2680, 'MATUREIA', 15, '2509396', 1),
+ (2681, 'MOGEIRO', 15, '2509404', 1),
+ (2682, 'MONTADAS', 15, '2509503', 1),
+ (2683, 'MONTE HOREBE', 15, '2509602', 1),
+ (2684, 'MONTEIRO', 15, '2509701', 1),
+ (2685, 'MULUNGU', 15, '2509800', 1),
+ (2686, 'NATUBA', 15, '2509909', 1),
+ (2687, 'NAZAREZINHO', 15, '2510006', 1),
+ (2688, 'NOVA FLORESTA', 15, '2510105', 1),
+ (2689, 'NOVA OLINDA', 15, '2510204', 1),
+ (2690, 'NOVA PALMEIRA', 15, '2510303', 1),
+ (2691, 'OLHO DAGUA', 15, '2510402', 1),
+ (2692, 'OLIVEDOS', 15, '2510501', 1),
+ (2693, 'OURO VELHO', 15, '2510600', 1),
+ (2694, 'PARARI', 15, '2510659', 1),
+ (2695, 'PASSAGEM', 15, '2510709', 1),
+ (2696, 'PATOS', 15, '2510808', 1),
+ (2697, 'PAULISTA', 15, '2510907', 1),
+ (2698, 'PEDRA BRANCA', 15, '2511004', 1),
+ (2699, 'PEDRA LAVRADA', 15, '2511103', 1),
+ (2700, 'PEDRAS DE FOGO', 15, '2511202', 1),
+ (2701, 'PIANCO', 15, '2511301', 1),
+ (2702, 'PICUI', 15, '2511400', 1),
+ (2703, 'PILAR', 15, '2511509', 1),
+ (2704, 'PILOES', 15, '2511608', 1),
+ (2705, 'PILOEZINHOS', 15, '2511707', 1),
+ (2706, 'PIRPIRITUBA', 15, '2511806', 1),
+ (2707, 'PITIMBU', 15, '2511905', 1),
+ (2708, 'POCINHOS', 15, '2512002', 1),
+ (2709, 'POCO DANTAS', 15, '2512036', 1),
+ (2710, 'POCO DE JOSE DE MOURA', 15, '2512077', 1),
+ (2711, 'POMBAL', 15, '2512101', 1),
+ (2712, 'PRATA', 15, '2512200', 1),
+ (2713, 'PRINCESA ISABEL', 15, '2512309', 1),
+ (2714, 'PUXINANA', 15, '2512408', 1),
+ (2715, 'QUEIMADAS', 15, '2512507', 1),
+ (2716, 'QUIXABA', 15, '2512606', 1),
+ (2717, 'REMIGIO', 15, '2512705', 1),
+ (2718, 'PEDRO REGIS', 15, '2512721', 1),
+ (2719, 'RIACHAO', 15, '2512747', 1),
+ (2720, 'RIACHAO DO BACAMARTE', 15, '2512754', 1),
+ (2721, 'RIACHAO DO POCO', 15, '2512762', 1),
+ (2722, 'RIACHO DE SANTO ANTONIO', 15, '2512788', 1),
+ (2723, 'RIACHO DOS CAVALOS', 15, '2512804', 1),
+ (2724, 'RIO TINTO', 15, '2512903', 1),
+ (2725, 'SALGADINHO', 15, '2513000', 1),
+ (2726, 'SALGADO DE SAO FELIX', 15, '2513109', 1),
+ (2727, 'SANTA CECILIA', 15, '2513158', 1),
+ (2728, 'SANTA CRUZ', 15, '2513208', 1),
+ (2729, 'SANTA HELENA', 15, '2513307', 1),
+ (2730, 'SANTA INES', 15, '2513356', 1),
+ (2731, 'SANTA LUZIA', 15, '2513406', 1),
+ (2732, 'SANTANA DE MANGUEIRA', 15, '2513505', 1),
+ (2733, 'SANTANA DOS GARROTES', 15, '2513604', 1),
+ (2734, 'SANTAREM', 15, '2513653', 1),
+ (2735, 'SANTA RITA', 15, '2513703', 1),
+ (2736, 'SANTA TERESINHA', 15, '2513802', 1),
+ (2737, 'SANTO ANDRE', 15, '2513851', 1),
+ (2738, 'SAO BENTO', 15, '2513901', 1),
+ (2739, 'SAO BENTINHO', 15, '2513927', 1),
+ (2740, 'SAO DOMINGOS DO CARIRI', 15, '2513943', 1),
+ (2741, 'SAO DOMINGOS', 15, '2513968', 1),
+ (2742, 'SAO FRANCISCO', 15, '2513984', 1),
+ (2743, 'SAO JOAO DO CARIRI', 15, '2514008', 1),
+ (2744, 'SAO JOAO DO TIGRE', 15, '2514107', 1),
+ (2745, 'SAO JOSE DA LAGOA TAPADA', 15, '2514206', 1),
+ (2746, 'SAO JOSE DE CAIANA', 15, '2514305', 1),
+ (2747, 'SAO JOSE DE ESPINHARAS', 15, '2514404', 1),
+ (2748, 'SAO JOSE DOS RAMOS', 15, '2514453', 1),
+ (2749, 'SAO JOSE DE PIRANHAS', 15, '2514503', 1),
+ (2750, 'SAO JOSE DE PRINCESA', 15, '2514552', 1),
+ (2751, 'SAO JOSE DO BONFIM', 15, '2514602', 1),
+ (2752, 'SAO JOSE DO BREJO DO CRUZ', 15, '2514651', 1),
+ (2753, 'SAO JOSE DO SABUGI', 15, '2514701', 1),
+ (2754, 'SAO JOSE DOS CORDEIROS', 15, '2514800', 1),
+ (2755, 'SAO MAMEDE', 15, '2514909', 1),
+ (2756, 'SAO MIGUEL DE TAIPU', 15, '2515005', 1),
+ (2757, 'SAO SEBASTIAO DE LAGOA DE ROCA', 15, '2515104', 1),
+ (2758, 'SAO SEBASTIAO DO UMBUZEIRO', 15, '2515203', 1),
+ (2759, 'SAPE', 15, '2515302', 1),
+ (2760, 'SERIDO', 15, '2515401', 1),
+ (2761, 'SERRA BRANCA', 15, '2515500', 1),
+ (2762, 'SERRA DA RAIZ', 15, '2515609', 1),
+ (2763, 'SERRA GRANDE', 15, '2515708', 1),
+ (2764, 'SERRA REDONDA', 15, '2515807', 1),
+ (2765, 'SERRARIA', 15, '2515906', 1),
+ (2766, 'SERTAOZINHO', 15, '2515930', 1),
+ (2767, 'SOBRADO', 15, '2515971', 1),
+ (2768, 'SOLANEA', 15, '2516003', 1),
+ (2769, 'SOLEDADE', 15, '2516102', 1),
+ (2770, 'SOSSEGO', 15, '2516151', 1),
+ (2771, 'SOUSA', 15, '2516201', 1),
+ (2772, 'SUME', 15, '2516300', 1),
+ (2773, 'TACIMA', 15, '2516409', 1),
+ (2774, 'TAPEROA', 15, '2516508', 1),
+ (2775, 'TAVARES', 15, '2516607', 1),
+ (2776, 'TEIXEIRA', 15, '2516706', 1),
+ (2777, 'TENORIO', 15, '2516755', 1),
+ (2778, 'TRIUNFO', 15, '2516805', 1),
+ (2779, 'UIRAUNA', 15, '2516904', 1),
+ (2780, 'UMBUZEIRO', 15, '2517001', 1),
+ (2781, 'VARZEA', 15, '2517100', 1),
+ (2782, 'VIEIROPOLIS', 15, '2517209', 1),
+ (2783, 'ZABELE', 15, '2517407', 1),
+ (2784, 'ABREU E LIMA', 16, '2600054', 1),
+ (2785, 'AFOGADOS DA INGAZEIRA', 16, '2600104', 1),
+ (2786, 'AFRANIO', 16, '2600203', 1),
+ (2787, 'AGRESTINA', 16, '2600302', 1),
+ (2788, 'AGUA PRETA', 16, '2600401', 1),
+ (2789, 'AGUAS BELAS', 16, '2600500', 1),
+ (2790, 'ALAGOINHA', 16, '2600609', 1),
+ (2791, 'ALIANCA', 16, '2600708', 1),
+ (2792, 'ALTINHO', 16, '2600807', 1),
+ (2793, 'AMARAJI', 16, '2600906', 1),
+ (2794, 'ANGELIM', 16, '2601003', 1),
+ (2795, 'ARACOIABA', 16, '2601052', 1),
+ (2796, 'ARARIPINA', 16, '2601102', 1),
+ (2797, 'ARCOVERDE', 16, '2601201', 1),
+ (2798, 'BARRA DE GUABIRABA', 16, '2601300', 1),
+ (2799, 'BARREIROS', 16, '2601409', 1),
+ (2800, 'BELEM DE MARIA', 16, '2601508', 1),
+ (2801, 'BELEM DO SAO FRANCISCO', 16, '2601607', 1),
+ (2802, 'BELO JARDIM', 16, '2601706', 1),
+ (2803, 'BETANIA', 16, '2601805', 1),
+ (2804, 'BEZERROS', 16, '2601904', 1),
+ (2805, 'BODOCO', 16, '2602001', 1),
+ (2806, 'BOM CONSELHO', 16, '2602100', 1),
+ (2807, 'BOM JARDIM', 16, '2602209', 1),
+ (2808, 'BONITO', 16, '2602308', 1),
+ (2809, 'BREJAO', 16, '2602407', 1),
+ (2810, 'BREJINHO', 16, '2602506', 1),
+ (2811, 'BREJO DA MADRE DE DEUS', 16, '2602605', 1),
+ (2812, 'BUENOS AIRES', 16, '2602704', 1),
+ (2813, 'BUIQUE', 16, '2602803', 1),
+ (2814, 'CABO DE SANTO AGOSTINHO', 16, '2602902', 1),
+ (2815, 'CABROBO', 16, '2603009', 1),
+ (2816, 'CACHOEIRINHA', 16, '2603108', 1),
+ (2817, 'CAETES', 16, '2603207', 1),
+ (2818, 'CALCADO', 16, '2603306', 1),
+ (2819, 'CALUMBI', 16, '2603405', 1),
+ (2820, 'CAMARAGIBE', 16, '2603454', 1),
+ (2821, 'CAMOCIM DE SAO FELIX', 16, '2603504', 1),
+ (2822, 'CAMUTANGA', 16, '2603603', 1),
+ (2823, 'CANHOTINHO', 16, '2603702', 1),
+ (2824, 'CAPOEIRAS', 16, '2603801', 1),
+ (2825, 'CARNAIBA', 16, '2603900', 1),
+ (2826, 'CARNAUBEIRA DA PENHA', 16, '2603926', 1),
+ (2827, 'CARPINA', 16, '2604007', 1),
+ (2828, 'CARUARU', 16, '2604106', 1),
+ (2829, 'CASINHAS', 16, '2604155', 1),
+ (2830, 'CATENDE', 16, '2604205', 1),
+ (2831, 'CEDRO', 16, '2604304', 1),
+ (2832, 'CHA DE ALEGRIA', 16, '2604403', 1),
+ (2833, 'CHA GRANDE', 16, '2604502', 1),
+ (2834, 'CONDADO', 16, '2604601', 1),
+ (2835, 'CORRENTES', 16, '2604700', 1),
+ (2836, 'CORTES', 16, '2604809', 1),
+ (2837, 'CUMARU', 16, '2604908', 1),
+ (2838, 'CUPIRA', 16, '2605004', 1),
+ (2839, 'CUSTODIA', 16, '2605103', 1),
+ (2840, 'DORMENTES', 16, '2605152', 1),
+ (2841, 'ESCADA', 16, '2605202', 1),
+ (2842, 'EXU', 16, '2605301', 1),
+ (2843, 'FEIRA NOVA', 16, '2605400', 1),
+ (2844, 'FERNANDO DE NORONHA', 16, '2605459', 1),
+ (2845, 'FERREIROS', 16, '2605509', 1),
+ (2846, 'FLORES', 16, '2605608', 1),
+ (2847, 'FLORESTA', 16, '2605707', 1),
+ (2848, 'FREI MIGUELINHO', 16, '2605806', 1),
+ (2849, 'GAMELEIRA', 16, '2605905', 1),
+ (2850, 'GARANHUNS', 16, '2606002', 1),
+ (2851, 'GLORIA DO GOITA', 16, '2606101', 1),
+ (2852, 'GOIANA', 16, '2606200', 1),
+ (2853, 'GRANITO', 16, '2606309', 1),
+ (2854, 'GRAVATA', 16, '2606408', 1),
+ (2855, 'IATI', 16, '2606507', 1),
+ (2856, 'IBIMIRIM', 16, '2606606', 1),
+ (2857, 'IBIRAJUBA', 16, '2606705', 1),
+ (2858, 'IGARASSU', 16, '2606804', 1),
+ (2859, 'IGUARACI', 16, '2606903', 1),
+ (2860, 'INAJA', 16, '2607000', 1),
+ (2861, 'INGAZEIRA', 16, '2607109', 1),
+ (2862, 'IPOJUCA', 16, '2607208', 1),
+ (2863, 'IPUBI', 16, '2607307', 1),
+ (2864, 'ITACURUBA', 16, '2607406', 1),
+ (2865, 'ITAIBA', 16, '2607505', 1),
+ (2866, 'ILHA DE ITAMARACA', 16, '2607604', 1),
+ (2867, 'ITAMBE', 16, '2607653', 1),
+ (2868, 'ITAPETIM', 16, '2607703', 1),
+ (2869, 'ITAPISSUMA', 16, '2607752', 1),
+ (2870, 'ITAQUITINGA', 16, '2607802', 1),
+ (2871, 'JABOATAO DOS GUARARAPES', 16, '2607901', 1),
+ (2872, 'JAQUEIRA', 16, '2607950', 1),
+ (2873, 'JATAUBA', 16, '2608008', 1),
+ (2874, 'JATOBA', 16, '2608057', 1),
+ (2875, 'JOAO ALFREDO', 16, '2608107', 1),
+ (2876, 'JOAQUIM NABUCO', 16, '2608206', 1),
+ (2877, 'JUCATI', 16, '2608255', 1),
+ (2878, 'JUPI', 16, '2608305', 1),
+ (2879, 'JUREMA', 16, '2608404', 1),
+ (2880, 'LAGOA DO CARRO', 16, '2608453', 1),
+ (2881, 'LAGOA DE ITAENGA', 16, '2608503', 1),
+ (2882, 'LAGOA DO OURO', 16, '2608602', 1),
+ (2883, 'LAGOA DOS GATOS', 16, '2608701', 1),
+ (2884, 'LAGOA GRANDE', 16, '2608750', 1),
+ (2885, 'LAJEDO', 16, '2608800', 1),
+ (2886, 'LIMOEIRO', 16, '2608909', 1),
+ (2887, 'MACAPARANA', 16, '2609006', 1),
+ (2888, 'MACHADOS', 16, '2609105', 1),
+ (2889, 'MANARI', 16, '2609154', 1),
+ (2890, 'MARAIAL', 16, '2609204', 1),
+ (2891, 'MIRANDIBA', 16, '2609303', 1),
+ (2892, 'MORENO', 16, '2609402', 1),
+ (2893, 'NAZARE DA MATA', 16, '2609501', 1),
+ (2894, 'OLINDA', 16, '2609600', 1),
+ (2895, 'OROBO', 16, '2609709', 1),
+ (2896, 'OROCO', 16, '2609808', 1),
+ (2897, 'OURICURI', 16, '2609907', 1),
+ (2898, 'PALMARES', 16, '2610004', 1),
+ (2899, 'PALMEIRINA', 16, '2610103', 1),
+ (2900, 'PANELAS', 16, '2610202', 1),
+ (2901, 'PARANATAMA', 16, '2610301', 1),
+ (2902, 'PARNAMIRIM', 16, '2610400', 1),
+ (2903, 'PASSIRA', 16, '2610509', 1),
+ (2904, 'PAUDALHO', 16, '2610608', 1),
+ (2905, 'PAULISTA', 16, '2610707', 1),
+ (2906, 'PEDRA', 16, '2610806', 1),
+ (2907, 'PESQUEIRA', 16, '2610905', 1),
+ (2908, 'PETROLANDIA', 16, '2611002', 1),
+ (2909, 'PETROLINA', 16, '2611101', 1),
+ (2910, 'POCAO', 16, '2611200', 1),
+ (2911, 'POMBOS', 16, '2611309', 1),
+ (2912, 'PRIMAVERA', 16, '2611408', 1),
+ (2913, 'QUIPAPA', 16, '2611507', 1),
+ (2914, 'QUIXABA', 16, '2611533', 1),
+ (2915, 'RECIFE', 16, '2611606', 1),
+ (2916, 'RIACHO DAS ALMAS', 16, '2611705', 1),
+ (2917, 'RIBEIRAO', 16, '2611804', 1),
+ (2918, 'RIO FORMOSO', 16, '2611903', 1),
+ (2919, 'SAIRE', 16, '2612000', 1),
+ (2920, 'SALGADINHO', 16, '2612109', 1),
+ (2921, 'SALGUEIRO', 16, '2612208', 1),
+ (2922, 'SALOA', 16, '2612307', 1),
+ (2923, 'SANHARO', 16, '2612406', 1),
+ (2924, 'SANTA CRUZ', 16, '2612455', 1),
+ (2925, 'SANTA CRUZ DA BAIXA VERDE', 16, '2612471', 1),
+ (2926, 'SANTA CRUZ DO CAPIBARIBE', 16, '2612505', 1),
+ (2927, 'SANTA FILOMENA', 16, '2612554', 1),
+ (2928, 'SANTA MARIA DA BOA VISTA', 16, '2612604', 1),
+ (2929, 'SANTA MARIA DO CAMBUCA', 16, '2612703', 1),
+ (2930, 'SANTA TEREZINHA', 16, '2612802', 1),
+ (2931, 'SAO BENEDITO DO SUL', 16, '2612901', 1),
+ (2932, 'SAO BENTO DO UNA', 16, '2613008', 1),
+ (2933, 'SAO CAITANO', 16, '2613107', 1),
+ (2934, 'SAO JOAO', 16, '2613206', 1),
+ (2935, 'SAO JOAQUIM DO MONTE', 16, '2613305', 1),
+ (2936, 'SAO JOSE DA COROA GRANDE', 16, '2613404', 1),
+ (2937, 'SAO JOSE DO BELMONTE', 16, '2613503', 1),
+ (2938, 'SAO JOSE DO EGITO', 16, '2613602', 1),
+ (2939, 'SAO LOURENCO DA MATA', 16, '2613701', 1),
+ (2940, 'SAO VICENTE FERRER', 16, '2613800', 1),
+ (2941, 'SERRA TALHADA', 16, '2613909', 1),
+ (2942, 'SERRITA', 16, '2614006', 1),
+ (2943, 'SERTANIA', 16, '2614105', 1),
+ (2944, 'SIRINHAEM', 16, '2614204', 1),
+ (2945, 'MOREILANDIA', 16, '2614303', 1),
+ (2946, 'SOLIDAO', 16, '2614402', 1),
+ (2947, 'SURUBIM', 16, '2614501', 1),
+ (2948, 'TABIRA', 16, '2614600', 1),
+ (2949, 'TACAIMBO', 16, '2614709', 1),
+ (2950, 'TACARATU', 16, '2614808', 1),
+ (2951, 'TAMANDARE', 16, '2614857', 1),
+ (2952, 'TAQUARITINGA DO NORTE', 16, '2615003', 1),
+ (2953, 'TEREZINHA', 16, '2615102', 1),
+ (2954, 'TERRA NOVA', 16, '2615201', 1),
+ (2955, 'TIMBAUBA', 16, '2615300', 1),
+ (2956, 'TORITAMA', 16, '2615409', 1),
+ (2957, 'TRACUNHAEM', 16, '2615508', 1),
+ (2958, 'TRINDADE', 16, '2615607', 1),
+ (2959, 'TRIUNFO', 16, '2615706', 1),
+ (2960, 'TUPANATINGA', 16, '2615805', 1),
+ (2961, 'TUPARETAMA', 16, '2615904', 1),
+ (2962, 'VENTUROSA', 16, '2616001', 1),
+ (2963, 'VERDEJANTE', 16, '2616100', 1),
+ (2964, 'VERTENTE DO LERIO', 16, '2616183', 1),
+ (2965, 'VERTENTES', 16, '2616209', 1),
+ (2966, 'VICENCIA', 16, '2616308', 1),
+ (2967, 'VITORIA DE SANTO ANTAO', 16, '2616407', 1),
+ (2968, 'XEXEU', 16, '2616506', 1),
+ (2969, 'ACAUA', 17, '2200053', 1),
+ (2970, 'AGRICOLANDIA', 17, '2200103', 1),
+ (2971, 'AGUA BRANCA', 17, '2200202', 1),
+ (2972, 'ALAGOINHA DO PIAUI', 17, '2200251', 1),
+ (2973, 'ALEGRETE DO PIAUI', 17, '2200277', 1),
+ (2974, 'ALTO LONGA', 17, '2200301', 1),
+ (2975, 'ALTOS', 17, '2200400', 1),
+ (2976, 'ALVORADA DO GURGUEIA', 17, '2200459', 1),
+ (2977, 'AMARANTE', 17, '2200509', 1),
+ (2978, 'ANGICAL DO PIAUI', 17, '2200608', 1),
+ (2979, 'ANISIO DE ABREU', 17, '2200707', 1),
+ (2980, 'ANTONIO ALMEIDA', 17, '2200806', 1),
+ (2981, 'AROAZES', 17, '2200905', 1),
+ (2982, 'AROEIRAS DO ITAIM', 17, '2200954', 1),
+ (2983, 'ARRAIAL', 17, '2201002', 1),
+ (2984, 'ASSUNCAO DO PIAUI', 17, '2201051', 1),
+ (2985, 'AVELINO LOPES', 17, '2201101', 1),
+ (2986, 'BAIXA GRANDE DO RIBEIRO', 17, '2201150', 1),
+ (2987, 'BARRA DALCANTARA', 17, '2201176', 1),
+ (2988, 'BARRAS', 17, '2201200', 1),
+ (2989, 'BARREIRAS DO PIAUI', 17, '2201309', 1),
+ (2990, 'BARRO DURO', 17, '2201408', 1),
+ (2991, 'BATALHA', 17, '2201507', 1),
+ (2992, 'BELA VISTA DO PIAUI', 17, '2201556', 1),
+ (2993, 'BELEM DO PIAUI', 17, '2201572', 1),
+ (2994, 'BENEDITINOS', 17, '2201606', 1),
+ (2995, 'BERTOLINIA', 17, '2201705', 1),
+ (2996, 'BETANIA DO PIAUI', 17, '2201739', 1),
+ (2997, 'BOA HORA', 17, '2201770', 1),
+ (2998, 'BOCAINA', 17, '2201804', 1),
+ (2999, 'BOM JESUS', 17, '2201903', 1),
+ (3000, 'BOM PRINCIPIO DO PIAUI', 17, '2201919', 1),
+ (3001, 'BONFIM DO PIAUI', 17, '2201929', 1),
+ (3002, 'BOQUEIRAO DO PIAUI', 17, '2201945', 1),
+ (3003, 'BRASILEIRA', 17, '2201960', 1),
+ (3004, 'BREJO DO PIAUI', 17, '2201988', 1),
+ (3005, 'BURITI DOS LOPES', 17, '2202000', 1),
+ (3006, 'BURITI DOS MONTES', 17, '2202026', 1),
+ (3007, 'CABECEIRAS DO PIAUI', 17, '2202059', 1),
+ (3008, 'CAJAZEIRAS DO PIAUI', 17, '2202075', 1),
+ (3009, 'CAJUEIRO DA PRAIA', 17, '2202083', 1),
+ (3010, 'CALDEIRAO GRANDE DO PIAUI', 17, '2202091', 1),
+ (3011, 'CAMPINAS DO PIAUI', 17, '2202109', 1),
+ (3012, 'CAMPO ALEGRE DO FIDALGO', 17, '2202117', 1),
+ (3013, 'CAMPO GRANDE DO PIAUI', 17, '2202133', 1),
+ (3014, 'CAMPO LARGO DO PIAUI', 17, '2202174', 1),
+ (3015, 'CAMPO MAIOR', 17, '2202208', 1),
+ (3016, 'CANAVIEIRA', 17, '2202251', 1),
+ (3017, 'CANTO DO BURITI', 17, '2202307', 1),
+ (3018, 'CAPITAO DE CAMPOS', 17, '2202406', 1),
+ (3019, 'CAPITAO GERVASIO OLIVEIRA', 17, '2202455', 1),
+ (3020, 'CARACOL', 17, '2202505', 1),
+ (3021, 'CARAUBAS DO PIAUI', 17, '2202539', 1),
+ (3022, 'CARIDADE DO PIAUI', 17, '2202554', 1),
+ (3023, 'CASTELO DO PIAUI', 17, '2202604', 1),
+ (3024, 'CAXINGO', 17, '2202653', 1),
+ (3025, 'COCAL', 17, '2202703', 1),
+ (3026, 'COCAL DE TELHA', 17, '2202711', 1),
+ (3027, 'COCAL DOS ALVES', 17, '2202729', 1),
+ (3028, 'COIVARAS', 17, '2202737', 1),
+ (3029, 'COLONIA DO GURGUEIA', 17, '2202752', 1),
+ (3030, 'COLONIA DO PIAUI', 17, '2202778', 1),
+ (3031, 'CONCEICAO DO CANINDE', 17, '2202802', 1),
+ (3032, 'CORONEL JOSE DIAS', 17, '2202851', 1),
+ (3033, 'CORRENTE', 17, '2202901', 1),
+ (3034, 'CRISTALANDIA DO PIAUI', 17, '2203008', 1),
+ (3035, 'CRISTINO CASTRO', 17, '2203107', 1),
+ (3036, 'CURIMATA', 17, '2203206', 1),
+ (3037, 'CURRAIS', 17, '2203230', 1),
+ (3038, 'CURRALINHOS', 17, '2203255', 1),
+ (3039, 'CURRAL NOVO DO PIAUI', 17, '2203271', 1),
+ (3040, 'DEMERVAL LOBAO', 17, '2203305', 1),
+ (3041, 'DIRCEU ARCOVERDE', 17, '2203354', 1),
+ (3042, 'DOM EXPEDITO LOPES', 17, '2203404', 1),
+ (3043, 'DOMINGOS MOURAO', 17, '2203420', 1),
+ (3044, 'DOM INOCENCIO', 17, '2203453', 1),
+ (3045, 'ELESBAO VELOSO', 17, '2203503', 1),
+ (3046, 'ELISEU MARTINS', 17, '2203602', 1),
+ (3047, 'ESPERANTINA', 17, '2203701', 1),
+ (3048, 'FARTURA DO PIAUI', 17, '2203750', 1),
+ (3049, 'FLORES DO PIAUI', 17, '2203800', 1),
+ (3050, 'FLORESTA DO PIAUI', 17, '2203859', 1),
+ (3051, 'FLORIANO', 17, '2203909', 1),
+ (3052, 'FRANCINOPOLIS', 17, '2204006', 1),
+ (3053, 'FRANCISCO AYRES', 17, '2204105', 1),
+ (3054, 'FRANCISCO MACEDO', 17, '2204154', 1),
+ (3055, 'FRANCISCO SANTOS', 17, '2204204', 1),
+ (3056, 'FRONTEIRAS', 17, '2204303', 1),
+ (3057, 'GEMINIANO', 17, '2204352', 1),
+ (3058, 'GILBUES', 17, '2204402', 1),
+ (3059, 'GUADALUPE', 17, '2204501', 1),
+ (3060, 'GUARIBAS', 17, '2204550', 1),
+ (3061, 'HUGO NAPOLEAO', 17, '2204600', 1),
+ (3062, 'ILHA GRANDE', 17, '2204659', 1),
+ (3063, 'INHUMA', 17, '2204709', 1),
+ (3064, 'IPIRANGA DO PIAUI', 17, '2204808', 1),
+ (3065, 'ISAIAS COELHO', 17, '2204907', 1),
+ (3066, 'ITAINOPOLIS', 17, '2205003', 1),
+ (3067, 'BOILERPLATEEIRA', 17, '2205102', 1),
+ (3068, 'JACOBINA DO PIAUI', 17, '2205151', 1),
+ (3069, 'JAICOS', 17, '2205201', 1),
+ (3070, 'JARDIM DO MULATO', 17, '2205250', 1),
+ (3071, 'JATOBA DO PIAUI', 17, '2205276', 1),
+ (3072, 'JERUMENHA', 17, '2205300', 1),
+ (3073, 'JOAO COSTA', 17, '2205359', 1),
+ (3074, 'JOAQUIM PIRES', 17, '2205409', 1),
+ (3075, 'JOCA MARQUES', 17, '2205458', 1),
+ (3076, 'JOSE DE FREITAS', 17, '2205508', 1),
+ (3077, 'JUAZEIRO DO PIAUI', 17, '2205516', 1),
+ (3078, 'JULIO BORGES', 17, '2205524', 1),
+ (3079, 'JUREMA', 17, '2205532', 1),
+ (3080, 'LAGOINHA DO PIAUI', 17, '2205540', 1),
+ (3081, 'LAGOA ALEGRE', 17, '2205557', 1),
+ (3082, 'LAGOA DO BARRO DO PIAUI', 17, '2205565', 1),
+ (3083, 'LAGOA DE SAO FRANCISCO', 17, '2205573', 1),
+ (3084, 'LAGOA DO PIAUI', 17, '2205581', 1),
+ (3085, 'LAGOA DO SITIO', 17, '2205599', 1),
+ (3086, 'LANDRI SALES', 17, '2205607', 1),
+ (3087, 'LUIS CORREIA', 17, '2205706', 1),
+ (3088, 'LUZILANDIA', 17, '2205805', 1),
+ (3089, 'MADEIRO', 17, '2205854', 1),
+ (3090, 'MANOEL EMIDIO', 17, '2205904', 1),
+ (3091, 'MARCOLANDIA', 17, '2205953', 1),
+ (3092, 'MARCOS PARENTE', 17, '2206001', 1),
+ (3093, 'MASSAPE DO PIAUI', 17, '2206050', 1),
+ (3094, 'MATIAS OLIMPIO', 17, '2206100', 1),
+ (3095, 'MIGUEL ALVES', 17, '2206209', 1),
+ (3096, 'MIGUEL LEAO', 17, '2206308', 1),
+ (3097, 'MILTON BRANDAO', 17, '2206357', 1),
+ (3098, 'MONSENHOR GIL', 17, '2206407', 1),
+ (3099, 'MONSENHOR HIPOLITO', 17, '2206506', 1),
+ (3100, 'MONTE ALEGRE DO PIAUI', 17, '2206605', 1),
+ (3101, 'MORRO CABECA NO TEMPO', 17, '2206654', 1),
+ (3102, 'MORRO DO CHAPEU DO PIAUI', 17, '2206670', 1),
+ (3103, 'MURICI DOS PORTELAS', 17, '2206696', 1),
+ (3104, 'NAZARE DO PIAUI', 17, '2206704', 1),
+ (3105, 'NAZARIA', 17, '2206720', 1),
+ (3106, 'NOSSA SENHORA DE NAZARE', 17, '2206753', 1),
+ (3107, 'NOSSA SENHORA DOS REMEDIOS', 17, '2206803', 1),
+ (3108, 'NOVO ORIENTE DO PIAUI', 17, '2206902', 1),
+ (3109, 'NOVO SANTO ANTONIO', 17, '2206951', 1),
+ (3110, 'OEIRAS', 17, '2207009', 1),
+ (3111, 'OLHO DAGUA DO PIAUI', 17, '2207108', 1),
+ (3112, 'PADRE MARCOS', 17, '2207207', 1),
+ (3113, 'PAES LANDIM', 17, '2207306', 1),
+ (3114, 'PAJEU DO PIAUI', 17, '2207355', 1),
+ (3115, 'PALMEIRA DO PIAUI', 17, '2207405', 1),
+ (3116, 'PALMEIRAIS', 17, '2207504', 1),
+ (3117, 'PAQUETA', 17, '2207553', 1),
+ (3118, 'PARNAGUA', 17, '2207603', 1),
+ (3119, 'PARNAIBA', 17, '2207702', 1),
+ (3120, 'PASSAGEM FRANCA DO PIAUI', 17, '2207751', 1),
+ (3121, 'PATOS DO PIAUI', 17, '2207777', 1),
+ (3122, 'PAU DARCO DO PIAUI', 17, '2207793', 1),
+ (3123, 'PAULISTANA', 17, '2207801', 1),
+ (3124, 'PAVUSSU', 17, '2207850', 1),
+ (3125, 'PEDRO II', 17, '2207900', 1),
+ (3126, 'PEDRO LAURENTINO', 17, '2207934', 1),
+ (3127, 'NOVA SANTA RITA', 17, '2207959', 1),
+ (3128, 'PICOS', 17, '2208007', 1),
+ (3129, 'PIMENTEIRAS', 17, '2208106', 1),
+ (3130, 'PIO IX', 17, '2208205', 1),
+ (3131, 'PIRACURUCA', 17, '2208304', 1),
+ (3132, 'PIRIPIRI', 17, '2208403', 1),
+ (3133, 'PORTO', 17, '2208502', 1),
+ (3134, 'PORTO ALEGRE DO PIAUI', 17, '2208551', 1),
+ (3135, 'PRATA DO PIAUI', 17, '2208601', 1),
+ (3136, 'QUEIMADA NOVA', 17, '2208650', 1),
+ (3137, 'REDENCAO DO GURGUEIA', 17, '2208700', 1),
+ (3138, 'REGENERACAO', 17, '2208809', 1),
+ (3139, 'RIACHO FRIO', 17, '2208858', 1),
+ (3140, 'RIBEIRA DO PIAUI', 17, '2208874', 1),
+ (3141, 'RIBEIRO GONCALVES', 17, '2208908', 1),
+ (3142, 'RIO GRANDE DO PIAUI', 17, '2209005', 1),
+ (3143, 'SANTA CRUZ DO PIAUI', 17, '2209104', 1),
+ (3144, 'SANTA CRUZ DOS MILAGRES', 17, '2209153', 1),
+ (3145, 'SANTA FILOMENA', 17, '2209203', 1),
+ (3146, 'SANTA LUZ', 17, '2209302', 1),
+ (3147, 'SANTANA DO PIAUI', 17, '2209351', 1),
+ (3148, 'SANTA ROSA DO PIAUI', 17, '2209377', 1),
+ (3149, 'SANTO ANTONIO DE LISBOA', 17, '2209401', 1),
+ (3150, 'SANTO ANTONIO DOS MILAGRES', 17, '2209450', 1),
+ (3151, 'SANTO INACIO DO PIAUI', 17, '2209500', 1),
+ (3152, 'SAO BRAZ DO PIAUI', 17, '2209559', 1),
+ (3153, 'SAO FELIX DO PIAUI', 17, '2209609', 1),
+ (3154, 'SAO FRANCISCO DE ASSIS DO PIAUI', 17, '2209658', 1),
+ (3155, 'SAO FRANCISCO DO PIAUI', 17, '2209708', 1),
+ (3156, 'SAO GONCALO DO GURGUEIA', 17, '2209757', 1),
+ (3157, 'SAO GONCALO DO PIAUI', 17, '2209807', 1),
+ (3158, 'SAO JOAO DA CANABRAVA', 17, '2209856', 1),
+ (3159, 'SAO JOAO DA FRONTEIRA', 17, '2209872', 1),
+ (3160, 'SAO JOAO DA SERRA', 17, '2209906', 1),
+ (3161, 'SAO JOAO DA VARJOTA', 17, '2209955', 1),
+ (3162, 'SAO JOAO DO ARRAIAL', 17, '2209971', 1),
+ (3163, 'SAO JOAO DO PIAUI', 17, '2210003', 1),
+ (3164, 'SAO JOSE DO DIVINO', 17, '2210052', 1),
+ (3165, 'SAO JOSE DO PEIXE', 17, '2210102', 1),
+ (3166, 'SAO JOSE DO PIAUI', 17, '2210201', 1),
+ (3167, 'SAO JULIAO', 17, '2210300', 1),
+ (3168, 'SAO LOURENCO DO PIAUI', 17, '2210359', 1),
+ (3169, 'SAO LUIS DO PIAUI', 17, '2210375', 1),
+ (3170, 'SAO MIGUEL DA BAIXA GRANDE', 17, '2210383', 1),
+ (3171, 'SAO MIGUEL DO FIDALGO', 17, '2210391', 1),
+ (3172, 'SAO MIGUEL DO TAPUIO', 17, '2210409', 1),
+ (3173, 'SAO PEDRO DO PIAUI', 17, '2210508', 1),
+ (3174, 'SAO RAIMUNDO NONATO', 17, '2210607', 1),
+ (3175, 'SEBASTIAO BARROS', 17, '2210623', 1),
+ (3176, 'SEBASTIAO LEAL', 17, '2210631', 1),
+ (3177, 'SIGEFREDO PACHECO', 17, '2210656', 1),
+ (3178, 'SIMOES', 17, '2210706', 1),
+ (3179, 'SIMPLICIO MENDES', 17, '2210805', 1),
+ (3180, 'SOCORRO DO PIAUI', 17, '2210904', 1),
+ (3181, 'SUSSUAPARA', 17, '2210938', 1),
+ (3182, 'TAMBORIL DO PIAUI', 17, '2210953', 1),
+ (3183, 'TANQUE DO PIAUI', 17, '2210979', 1),
+ (3184, 'TERESINA', 17, '2211001', 1),
+ (3185, 'UNIAO', 17, '2211100', 1),
+ (3186, 'URUCUI', 17, '2211209', 1),
+ (3187, 'VALENCA DO PIAUI', 17, '2211308', 1),
+ (3188, 'VARZEA BRANCA', 17, '2211357', 1),
+ (3189, 'VARZEA GRANDE', 17, '2211407', 1),
+ (3190, 'VERA MENDES', 17, '2211506', 1),
+ (3191, 'VILA NOVA DO PIAUI', 17, '2211605', 1),
+ (3192, 'WALL FERRAZ', 17, '2211704', 1),
+ (3193, 'ABATIA', 18, '4100103', 1),
+ (3194, 'ADRIANOPOLIS', 18, '4100202', 1),
+ (3195, 'AGUDOS DO SUL', 18, '4100301', 1),
+ (3196, 'ALMIRANTE TAMANDARE', 18, '4100400', 1),
+ (3197, 'ALTAMIRA DO PARANA', 18, '4100459', 1),
+ (3198, 'ALTONIA', 18, '4100509', 1),
+ (3199, 'ALTO PARANA', 18, '4100608', 1),
+ (3200, 'ALTO PIQUIRI', 18, '4100707', 1),
+ (3201, 'ALVORADA DO SUL', 18, '4100806', 1),
+ (3202, 'AMAPORA', 18, '4100905', 1),
+ (3203, 'AMPERE', 18, '4101002', 1),
+ (3204, 'ANAHY', 18, '4101051', 1),
+ (3205, 'ANDIRA', 18, '4101101', 1),
+ (3206, 'ANGULO', 18, '4101150', 1),
+ (3207, 'ANTONINA', 18, '4101200', 1),
+ (3208, 'ANTONIO OLINTO', 18, '4101309', 1),
+ (3209, 'APUCARANA', 18, '4101408', 1),
+ (3210, 'ARAPONGAS', 18, '4101507', 1),
+ (3211, 'ARAPOTI', 18, '4101606', 1),
+ (3212, 'ARAPUA', 18, '4101655', 1),
+ (3213, 'ARARUNA', 18, '4101705', 1),
+ (3214, 'ARAUCARIA', 18, '4101804', 1),
+ (3215, 'ARIRANHA DO IVAI', 18, '4101853', 1),
+ (3216, 'ASSAI', 18, '4101903', 1),
+ (3217, 'ASSIS CHATEAUBRIAND', 18, '4102000', 1),
+ (3218, 'ASTORGA', 18, '4102109', 1),
+ (3219, 'ATALAIA', 18, '4102208', 1),
+ (3220, 'BALSA NOVA', 18, '4102307', 1),
+ (3221, 'BANDEIRANTES', 18, '4102406', 1),
+ (3222, 'BARBOSA FERRAZ', 18, '4102505', 1),
+ (3223, 'BARRACAO', 18, '4102604', 1),
+ (3224, 'BARRA DO JACARE', 18, '4102703', 1),
+ (3225, 'BELA VISTA DA CAROBA', 18, '4102752', 1),
+ (3226, 'BELA VISTA DO PARAISO', 18, '4102802', 1),
+ (3227, 'BITURUNA', 18, '4102901', 1),
+ (3228, 'BOA ESPERANCA', 18, '4103008', 1),
+ (3229, 'BOA ESPERANCA DO IGUACU', 18, '4103024', 1),
+ (3230, 'BOA VENTURA DE SAO ROQUE', 18, '4103040', 1),
+ (3231, 'BOA VISTA DA APARECIDA', 18, '4103057', 1),
+ (3232, 'BOCAIUVA DO SUL', 18, '4103107', 1),
+ (3233, 'BOM JESUS DO SUL', 18, '4103156', 1),
+ (3234, 'BOM SUCESSO', 18, '4103206', 1),
+ (3235, 'BOM SUCESSO DO SUL', 18, '4103222', 1),
+ (3236, 'BORRAZOPOLIS', 18, '4103305', 1),
+ (3237, 'BRAGANEY', 18, '4103354', 1),
+ (3238, 'BRASILANDIA DO SUL', 18, '4103370', 1),
+ (3239, 'CAFEARA', 18, '4103404', 1),
+ (3240, 'CAFELANDIA', 18, '4103453', 1),
+ (3241, 'CAFEZAL DO SUL', 18, '4103479', 1),
+ (3242, 'CALIFORNIA', 18, '4103503', 1),
+ (3243, 'CAMBARA', 18, '4103602', 1),
+ (3244, 'CAMBE', 18, '4103701', 1),
+ (3245, 'CAMBIRA', 18, '4103800', 1),
+ (3246, 'CAMPINA DA LAGOA', 18, '4103909', 1),
+ (3247, 'CAMPINA DO SIMAO', 18, '4103958', 1),
+ (3248, 'CAMPINA GRANDE DO SUL', 18, '4104006', 1),
+ (3249, 'CAMPO BONITO', 18, '4104055', 1),
+ (3250, 'CAMPO DO TENENTE', 18, '4104105', 1),
+ (3251, 'CAMPO LARGO', 18, '4104204', 1),
+ (3252, 'CAMPO MAGRO', 18, '4104253', 1),
+ (3253, 'CAMPO MOURAO', 18, '4104303', 1),
+ (3254, 'CANDIDO DE ABREU', 18, '4104402', 1),
+ (3255, 'CANDOI', 18, '4104428', 1),
+ (3256, 'CANTAGALO', 18, '4104451', 1),
+ (3257, 'CAPANEMA', 18, '4104501', 1),
+ (3258, 'CAPITAO LEONIDAS MARQUES', 18, '4104600', 1),
+ (3259, 'CARAMBEI', 18, '4104659', 1),
+ (3260, 'CARLOPOLIS', 18, '4104709', 1),
+ (3261, 'CASCAVEL', 18, '4104808', 1),
+ (3262, 'CASTRO', 18, '4104907', 1),
+ (3263, 'CATANDUVAS', 18, '4105003', 1),
+ (3264, 'CENTENARIO DO SUL', 18, '4105102', 1),
+ (3265, 'CERRO AZUL', 18, '4105201', 1),
+ (3266, 'CEU AZUL', 18, '4105300', 1),
+ (3267, 'CHOPINZINHO', 18, '4105409', 1),
+ (3268, 'CIANORTE', 18, '4105508', 1),
+ (3269, 'CIDADE GAUCHA', 18, '4105607', 1),
+ (3270, 'CLEVELANDIA', 18, '4105706', 1),
+ (3271, 'COLOMBO', 18, '4105805', 1),
+ (3272, 'COLORADO', 18, '4105904', 1),
+ (3273, 'CONGONHINHAS', 18, '4106001', 1),
+ (3274, 'CONSELHEIRO MAIRINCK', 18, '4106100', 1),
+ (3275, 'CONTENDA', 18, '4106209', 1),
+ (3276, 'CORBELIA', 18, '4106308', 1),
+ (3277, 'CORNELIO PROCOPIO', 18, '4106407', 1),
+ (3278, 'CORONEL DOMINGOS SOARES', 18, '4106456', 1),
+ (3279, 'CORONEL VIVIDA', 18, '4106506', 1),
+ (3280, 'CORUMBATAI DO SUL', 18, '4106555', 1),
+ (3281, 'CRUZEIRO DO IGUACU', 18, '4106571', 1),
+ (3282, 'CRUZEIRO DO OESTE', 18, '4106605', 1),
+ (3283, 'CRUZEIRO DO SUL', 18, '4106704', 1),
+ (3284, 'CRUZ MACHADO', 18, '4106803', 1),
+ (3285, 'CRUZMALTINA', 18, '4106852', 1),
+ (3286, 'CURITIBA', 18, '4106902', 1),
+ (3287, 'CURIUVA', 18, '4107009', 1),
+ (3288, 'DIAMANTE DO NORTE', 18, '4107108', 1),
+ (3289, 'DIAMANTE DO SUL', 18, '4107124', 1),
+ (3290, 'DIAMANTE DOESTE', 18, '4107157', 1),
+ (3291, 'DOIS VIZINHOS', 18, '4107207', 1),
+ (3292, 'DOURADINA', 18, '4107256', 1),
+ (3293, 'DOUTOR CAMARGO', 18, '4107306', 1),
+ (3294, 'ENEAS MARQUES', 18, '4107405', 1),
+ (3295, 'ENGENHEIRO BELTRAO', 18, '4107504', 1),
+ (3296, 'ESPERANCA NOVA', 18, '4107520', 1),
+ (3297, 'ENTRE RIOS DO OESTE', 18, '4107538', 1),
+ (3298, 'ESPIGAO ALTO DO IGUACU', 18, '4107546', 1),
+ (3299, 'FAROL', 18, '4107553', 1),
+ (3300, 'FAXINAL', 18, '4107603', 1),
+ (3301, 'FAZENDA RIO GRANDE', 18, '4107652', 1),
+ (3302, 'FENIX', 18, '4107702', 1),
+ (3303, 'FERNANDES PINHEIRO', 18, '4107736', 1),
+ (3304, 'FIGUEIRA', 18, '4107751', 1),
+ (3305, 'FLORAI', 18, '4107801', 1),
+ (3306, 'FLOR DA SERRA DO SUL', 18, '4107850', 1),
+ (3307, 'FLORESTA', 18, '4107900', 1),
+ (3308, 'FLORESTOPOLIS', 18, '4108007', 1),
+ (3309, 'FLORIDA', 18, '4108106', 1),
+ (3310, 'FORMOSA DO OESTE', 18, '4108205', 1),
+ (3311, 'FOZ DO IGUACU', 18, '4108304', 1),
+ (3312, 'FRANCISCO ALVES', 18, '4108320', 1),
+ (3313, 'FRANCISCO BELTRAO', 18, '4108403', 1),
+ (3314, 'FOZ DO JORDAO', 18, '4108452', 1),
+ (3315, 'GENERAL CARNEIRO', 18, '4108502', 1),
+ (3316, 'GODOY MOREIRA', 18, '4108551', 1),
+ (3317, 'GOIOERE', 18, '4108601', 1),
+ (3318, 'GOIOXIM', 18, '4108650', 1),
+ (3319, 'GRANDES RIOS', 18, '4108700', 1),
+ (3320, 'GUAIRA', 18, '4108809', 1),
+ (3321, 'GUAIRACA', 18, '4108908', 1),
+ (3322, 'GUAMIRANGA', 18, '4108957', 1),
+ (3323, 'GUAPIRAMA', 18, '4109005', 1),
+ (3324, 'GUAPOREMA', 18, '4109104', 1),
+ (3325, 'GUARACI', 18, '4109203', 1),
+ (3326, 'GUARANIACU', 18, '4109302', 1),
+ (3327, 'GUARAPUAVA', 18, '4109401', 1),
+ (3328, 'GUARAQUECABA', 18, '4109500', 1),
+ (3329, 'GUARATUBA', 18, '4109609', 1),
+ (3330, 'HONORIO SERPA', 18, '4109658', 1),
+ (3331, 'IBAITI', 18, '4109708', 1),
+ (3332, 'IBEMA', 18, '4109757', 1),
+ (3333, 'IBIPORA', 18, '4109807', 1),
+ (3334, 'ICARAIMA', 18, '4109906', 1),
+ (3335, 'IGUARACU', 18, '4110003', 1),
+ (3336, 'IGUATU', 18, '4110052', 1),
+ (3337, 'IMBAU', 18, '4110078', 1),
+ (3338, 'IMBITUVA', 18, '4110102', 1),
+ (3339, 'INACIO MARTINS', 18, '4110201', 1),
+ (3340, 'INAJA', 18, '4110300', 1),
+ (3341, 'INDIANOPOLIS', 18, '4110409', 1),
+ (3342, 'IPIRANGA', 18, '4110508', 1),
+ (3343, 'IPORA', 18, '4110607', 1),
+ (3344, 'IRACEMA DO OESTE', 18, '4110656', 1),
+ (3345, 'IRATI', 18, '4110706', 1),
+ (3346, 'IRETAMA', 18, '4110805', 1),
+ (3347, 'ITAGUAJE', 18, '4110904', 1),
+ (3348, 'ITAIPULANDIA', 18, '4110953', 1),
+ (3349, 'ITAMBARACA', 18, '4111001', 1),
+ (3350, 'ITAMBE', 18, '4111100', 1),
+ (3351, 'ITAPEJARA DOESTE', 18, '4111209', 1),
+ (3352, 'ITAPERUCU', 18, '4111258', 1),
+ (3353, 'BOILERPLATENA DO SUL', 18, '4111308', 1),
+ (3354, 'IVAI', 18, '4111407', 1),
+ (3355, 'IVAIPORA', 18, '4111506', 1),
+ (3356, 'IVATE', 18, '4111555', 1),
+ (3357, 'IVATUBA', 18, '4111605', 1),
+ (3358, 'JABOTI', 18, '4111704', 1),
+ (3359, 'JACAREZINHO', 18, '4111803', 1),
+ (3360, 'JAGUAPITA', 18, '4111902', 1),
+ (3361, 'JAGUARIAIVA', 18, '4112009', 1),
+ (3362, 'JANDAIA DO SUL', 18, '4112108', 1),
+ (3363, 'JANIOPOLIS', 18, '4112207', 1),
+ (3364, 'JAPIRA', 18, '4112306', 1),
+ (3365, 'JAPURA', 18, '4112405', 1),
+ (3366, 'JARDIM ALEGRE', 18, '4112504', 1),
+ (3367, 'JARDIM OLINDA', 18, '4112603', 1),
+ (3368, 'JATAIZINHO', 18, '4112702', 1),
+ (3369, 'JESUITAS', 18, '4112751', 1),
+ (3370, 'JOAQUIM TAVORA', 18, '4112801', 1),
+ (3371, 'JUNDIAI DO SUL', 18, '4112900', 1),
+ (3372, 'JURANDA', 18, '4112959', 1),
+ (3373, 'JUSSARA', 18, '4113007', 1),
+ (3374, 'KALORE', 18, '4113106', 1),
+ (3375, 'LAPA', 18, '4113205', 1),
+ (3376, 'LARANJAL', 18, '4113254', 1),
+ (3377, 'LARANJEIRAS DO SUL', 18, '4113304', 1),
+ (3378, 'LEOPOLIS', 18, '4113403', 1),
+ (3379, 'LIDIANOPOLIS', 18, '4113429', 1),
+ (3380, 'LINDOESTE', 18, '4113452', 1),
+ (3381, 'LOANDA', 18, '4113502', 1),
+ (3382, 'LOBATO', 18, '4113601', 1),
+ (3383, 'LONDRINA', 18, '4113700', 1),
+ (3384, 'LUIZIANA', 18, '4113734', 1),
+ (3385, 'LUNARDELLI', 18, '4113759', 1),
+ (3386, 'LUPIONOPOLIS', 18, '4113809', 1),
+ (3387, 'MALLET', 18, '4113908', 1),
+ (3388, 'MAMBORE', 18, '4114005', 1),
+ (3389, 'MANDAGUACU', 18, '4114104', 1),
+ (3390, 'MANDAGUARI', 18, '4114203', 1),
+ (3391, 'MANDIRITUBA', 18, '4114302', 1),
+ (3392, 'MANFRINOPOLIS', 18, '4114351', 1),
+ (3393, 'MANGUEIRINHA', 18, '4114401', 1),
+ (3394, 'MANOEL RIBAS', 18, '4114500', 1),
+ (3395, 'MARECHAL CANDIDO RONDON', 18, '4114609', 1),
+ (3396, 'MARIA HELENA', 18, '4114708', 1),
+ (3397, 'MARIALVA', 18, '4114807', 1),
+ (3398, 'MARILANDIA DO SUL', 18, '4114906', 1),
+ (3399, 'MARILENA', 18, '4115002', 1),
+ (3400, 'MARILUZ', 18, '4115101', 1),
+ (3401, 'MARINGA', 18, '4115200', 1),
+ (3402, 'MARIOPOLIS', 18, '4115309', 1),
+ (3403, 'MARIPA', 18, '4115358', 1),
+ (3404, 'MARMELEIRO', 18, '4115408', 1),
+ (3405, 'MARQUINHO', 18, '4115457', 1),
+ (3406, 'MARUMBI', 18, '4115507', 1),
+ (3407, 'MATELANDIA', 18, '4115606', 1),
+ (3408, 'MATINHOS', 18, '4115705', 1),
+ (3409, 'MATO RICO', 18, '4115739', 1),
+ (3410, 'MAUA DA SERRA', 18, '4115754', 1),
+ (3411, 'MEDIANEIRA', 18, '4115804', 1),
+ (3412, 'MERCEDES', 18, '4115853', 1),
+ (3413, 'MIRADOR', 18, '4115903', 1),
+ (3414, 'MIRASELVA', 18, '4116000', 1),
+ (3415, 'MISSAL', 18, '4116059', 1),
+ (3416, 'MOREIRA SALES', 18, '4116109', 1),
+ (3417, 'MORRETES', 18, '4116208', 1),
+ (3418, 'MUNHOZ DE MELO', 18, '4116307', 1),
+ (3419, 'NOSSA SENHORA DAS GRACAS', 18, '4116406', 1),
+ (3420, 'NOVA ALIANCA DO IVAI', 18, '4116505', 1),
+ (3421, 'NOVA AMERICA DA COLINA', 18, '4116604', 1),
+ (3422, 'NOVA AURORA', 18, '4116703', 1),
+ (3423, 'NOVA CANTU', 18, '4116802', 1),
+ (3424, 'NOVA ESPERANCA', 18, '4116901', 1),
+ (3425, 'NOVA ESPERANCA DO SUDOESTE', 18, '4116950', 1),
+ (3426, 'NOVA FATIMA', 18, '4117008', 1),
+ (3427, 'NOVA LARANJEIRAS', 18, '4117057', 1),
+ (3428, 'NOVA LONDRINA', 18, '4117107', 1),
+ (3429, 'NOVA OLIMPIA', 18, '4117206', 1),
+ (3430, 'NOVA SANTA BARBARA', 18, '4117214', 1),
+ (3431, 'NOVA SANTA ROSA', 18, '4117222', 1),
+ (3432, 'NOVA PRATA DO IGUACU', 18, '4117255', 1),
+ (3433, 'NOVA TEBAS', 18, '4117271', 1),
+ (3434, 'NOVO ITACOLOMI', 18, '4117297', 1),
+ (3435, 'ORTIGUEIRA', 18, '4117305', 1),
+ (3436, 'OURIZONA', 18, '4117404', 1),
+ (3437, 'OURO VERDE DO OESTE', 18, '4117453', 1),
+ (3438, 'PAICANDU', 18, '4117503', 1),
+ (3439, 'PALMAS', 18, '4117602', 1),
+ (3440, 'PALMEIRA', 18, '4117701', 1),
+ (3441, 'PALMITAL', 18, '4117800', 1),
+ (3442, 'PALOTINA', 18, '4117909', 1),
+ (3443, 'PARAISO DO NORTE', 18, '4118006', 1),
+ (3444, 'PARANACITY', 18, '4118105', 1),
+ (3445, 'PARANAGUA', 18, '4118204', 1),
+ (3446, 'PARANAPOEMA', 18, '4118303', 1),
+ (3447, 'PARANAVAI', 18, '4118402', 1),
+ (3448, 'PATO BRAGADO', 18, '4118451', 1),
+ (3449, 'PATO BRANCO', 18, '4118501', 1),
+ (3450, 'PAULA FREITAS', 18, '4118600', 1),
+ (3451, 'PAULO FRONTIN', 18, '4118709', 1),
+ (3452, 'PEABIRU', 18, '4118808', 1),
+ (3453, 'PEROBAL', 18, '4118857', 1),
+ (3454, 'PEROLA', 18, '4118907', 1),
+ (3455, 'PEROLA DOESTE', 18, '4119004', 1),
+ (3456, 'PIEN', 18, '4119103', 1),
+ (3457, 'PINHAIS', 18, '4119152', 1),
+ (3458, 'PINHALAO', 18, '4119202', 1),
+ (3459, 'PINHAL DE SAO BENTO', 18, '4119251', 1),
+ (3460, 'PINHAO', 18, '4119301', 1),
+ (3461, 'PIRAI DO SUL', 18, '4119400', 1),
+ (3462, 'PIRAQUARA', 18, '4119509', 1),
+ (3463, 'PITANGA', 18, '4119608', 1),
+ (3464, 'PITANGUEIRAS', 18, '4119657', 1),
+ (3465, 'PLANALTINA DO PARANA', 18, '4119707', 1),
+ (3466, 'PLANALTO', 18, '4119806', 1),
+ (3467, 'PONTA GROSSA', 18, '4119905', 1),
+ (3468, 'PONTAL DO PARANA', 18, '4119954', 1),
+ (3469, 'PORECATU', 18, '4120002', 1),
+ (3470, 'PORTO AMAZONAS', 18, '4120101', 1),
+ (3471, 'PORTO BARREIRO', 18, '4120150', 1),
+ (3472, 'PORTO RICO', 18, '4120200', 1),
+ (3473, 'PORTO VITORIA', 18, '4120309', 1),
+ (3474, 'PRADO FERREIRA', 18, '4120333', 1),
+ (3475, 'PRANCHITA', 18, '4120358', 1),
+ (3476, 'PRESIDENTE CASTELO BRANCO', 18, '4120408', 1),
+ (3477, 'PRIMEIRO DE MAIO', 18, '4120507', 1),
+ (3478, 'PRUDENTOPOLIS', 18, '4120606', 1),
+ (3479, 'QUARTO CENTENARIO', 18, '4120655', 1),
+ (3480, 'QUATIGUA', 18, '4120705', 1),
+ (3481, 'QUATRO BARRAS', 18, '4120804', 1),
+ (3482, 'QUATRO PONTES', 18, '4120853', 1),
+ (3483, 'QUEDAS DO IGUACU', 18, '4120903', 1),
+ (3484, 'QUERENCIA DO NORTE', 18, '4121000', 1),
+ (3485, 'QUINTA DO SOL', 18, '4121109', 1),
+ (3486, 'QUITANDINHA', 18, '4121208', 1),
+ (3487, 'RAMILANDIA', 18, '4121257', 1),
+ (3488, 'RANCHO ALEGRE', 18, '4121307', 1),
+ (3489, 'RANCHO ALEGRE DOESTE', 18, '4121356', 1),
+ (3490, 'REALEZA', 18, '4121406', 1),
+ (3491, 'REBOUCAS', 18, '4121505', 1),
+ (3492, 'RENASCENCA', 18, '4121604', 1),
+ (3493, 'RESERVA', 18, '4121703', 1),
+ (3494, 'RESERVA DO IGUACU', 18, '4121752', 1),
+ (3495, 'RIBEIRAO CLARO', 18, '4121802', 1),
+ (3496, 'RIBEIRAO DO PINHAL', 18, '4121901', 1),
+ (3497, 'RIO AZUL', 18, '4122008', 1),
+ (3498, 'RIO BOM', 18, '4122107', 1),
+ (3499, 'RIO BONITO DO IGUACU', 18, '4122156', 1),
+ (3500, 'RIO BRANCO DO IVAI', 18, '4122172', 1),
+ (3501, 'RIO BRANCO DO SUL', 18, '4122206', 1),
+ (3502, 'RIO NEGRO', 18, '4122305', 1),
+ (3503, 'ROLANDIA', 18, '4122404', 1),
+ (3504, 'RONCADOR', 18, '4122503', 1),
+ (3505, 'RONDON', 18, '4122602', 1),
+ (3506, 'ROSARIO DO IVAI', 18, '4122651', 1),
+ (3507, 'SABAUDIA', 18, '4122701', 1),
+ (3508, 'SALGADO FILHO', 18, '4122800', 1),
+ (3509, 'SALTO DO ITARARE', 18, '4122909', 1),
+ (3510, 'SALTO DO LONTRA', 18, '4123006', 1),
+ (3511, 'SANTA AMELIA', 18, '4123105', 1),
+ (3512, 'SANTA CECILIA DO PAVAO', 18, '4123204', 1),
+ (3513, 'SANTA CRUZ DE MONTE CASTELO', 18, '4123303', 1),
+ (3514, 'SANTA FE', 18, '4123402', 1),
+ (3515, 'SANTA HELENA', 18, '4123501', 1),
+ (3516, 'SANTA INES', 18, '4123600', 1),
+ (3517, 'SANTA ISABEL DO IVAI', 18, '4123709', 1),
+ (3518, 'SANTA IZABEL DO OESTE', 18, '4123808', 1),
+ (3519, 'SANTA LUCIA', 18, '4123824', 1),
+ (3520, 'SANTA MARIA DO OESTE', 18, '4123857', 1),
+ (3521, 'SANTA MARIANA', 18, '4123907', 1),
+ (3522, 'SANTA MONICA', 18, '4123956', 1),
+ (3523, 'SANTANA DO ITARARE', 18, '4124004', 1),
+ (3524, 'SANTA TEREZA DO OESTE', 18, '4124020', 1),
+ (3525, 'SANTA TEREZINHA DE ITAIPU', 18, '4124053', 1),
+ (3526, 'SANTO ANTONIO DA PLATINA', 18, '4124103', 1),
+ (3527, 'SANTO ANTONIO DO CAIUA', 18, '4124202', 1),
+ (3528, 'SANTO ANTONIO DO PARAISO', 18, '4124301', 1),
+ (3529, 'SANTO ANTONIO DO SUDOESTE', 18, '4124400', 1),
+ (3530, 'SANTO INACIO', 18, '4124509', 1),
+ (3531, 'SAO CARLOS DO IVAI', 18, '4124608', 1),
+ (3532, 'SAO JERONIMO DA SERRA', 18, '4124707', 1),
+ (3533, 'SAO JOAO', 18, '4124806', 1),
+ (3534, 'SAO JOAO DO CAIUA', 18, '4124905', 1),
+ (3535, 'SAO JOAO DO IVAI', 18, '4125001', 1),
+ (3536, 'SAO JOAO DO TRIUNFO', 18, '4125100', 1),
+ (3537, 'SAO JORGE DOESTE', 18, '4125209', 1),
+ (3538, 'SAO JORGE DO IVAI', 18, '4125308', 1),
+ (3539, 'SAO JORGE DO PATROCINIO', 18, '4125357', 1),
+ (3540, 'SAO JOSE DA BOA VISTA', 18, '4125407', 1),
+ (3541, 'SAO JOSE DAS PALMEIRAS', 18, '4125456', 1),
+ (3542, 'SAO JOSE DOS PINHAIS', 18, '4125506', 1),
+ (3543, 'SAO MANOEL DO PARANA', 18, '4125555', 1),
+ (3544, 'SAO MATEUS DO SUL', 18, '4125605', 1),
+ (3545, 'SAO MIGUEL DO IGUACU', 18, '4125704', 1),
+ (3546, 'SAO PEDRO DO IGUACU', 18, '4125753', 1),
+ (3547, 'SAO PEDRO DO IVAI', 18, '4125803', 1),
+ (3548, 'SAO PEDRO DO PARANA', 18, '4125902', 1),
+ (3549, 'SAO SEBASTIAO DA AMOREIRA', 18, '4126009', 1),
+ (3550, 'SAO TOME', 18, '4126108', 1),
+ (3551, 'SAPOPEMA', 18, '4126207', 1),
+ (3552, 'SARANDI', 18, '4126256', 1),
+ (3553, 'SAUDADE DO IGUACU', 18, '4126272', 1),
+ (3554, 'SENGES', 18, '4126306', 1),
+ (3555, 'SERRANOPOLIS DO IGUACU', 18, '4126355', 1),
+ (3556, 'SERTANEJA', 18, '4126405', 1),
+ (3557, 'SERTANOPOLIS', 18, '4126504', 1),
+ (3558, 'SIQUEIRA CAMPOS', 18, '4126603', 1),
+ (3559, 'SULINA', 18, '4126652', 1),
+ (3560, 'TAMARANA', 18, '4126678', 1),
+ (3561, 'TAMBOARA', 18, '4126702', 1),
+ (3562, 'TAPEJARA', 18, '4126801', 1),
+ (3563, 'TAPIRA', 18, '4126900', 1),
+ (3564, 'TEIXEIRA SOARES', 18, '4127007', 1),
+ (3565, 'TELEMACO BORBA', 18, '4127106', 1),
+ (3566, 'TERRA BOA', 18, '4127205', 1),
+ (3567, 'TERRA RICA', 18, '4127304', 1),
+ (3568, 'TERRA ROXA', 18, '4127403', 1),
+ (3569, 'TIBAGI', 18, '4127502', 1),
+ (3570, 'TIJUCAS DO SUL', 18, '4127601', 1),
+ (3571, 'TOLEDO', 18, '4127700', 1),
+ (3572, 'TOMAZINA', 18, '4127809', 1),
+ (3573, 'TRES BARRAS DO PARANA', 18, '4127858', 1),
+ (3574, 'TUNAS DO PARANA', 18, '4127882', 1),
+ (3575, 'TUNEIRAS DO OESTE', 18, '4127908', 1),
+ (3576, 'TUPASSI', 18, '4127957', 1),
+ (3577, 'TURVO', 18, '4127965', 1),
+ (3578, 'UBIRATA', 18, '4128005', 1),
+ (3579, 'UMUARAMA', 18, '4128104', 1),
+ (3580, 'UNIAO DA VITORIA', 18, '4128203', 1),
+ (3581, 'UNIFLOR', 18, '4128302', 1),
+ (3582, 'URAI', 18, '4128401', 1),
+ (3583, 'WENCESLAU BRAZ', 18, '4128500', 1),
+ (3584, 'VENTANIA', 18, '4128534', 1),
+ (3585, 'VERA CRUZ DO OESTE', 18, '4128559', 1),
+ (3586, 'VERE', 18, '4128609', 1),
+ (3587, 'ALTO PARAISO', 18, '4128625', 1),
+ (3588, 'DOUTOR ULYSSES', 18, '4128633', 1),
+ (3589, 'VIRMOND', 18, '4128658', 1),
+ (3590, 'VITORINO', 18, '4128708', 1),
+ (3591, 'XAMBRE', 18, '4128807', 1),
+ (3592, 'ANGRA DOS REIS', 19, '3300100', 1),
+ (3593, 'APERIBE', 19, '3300159', 1),
+ (3594, 'ARARUAMA', 19, '3300209', 1),
+ (3595, 'AREAL', 19, '3300225', 1),
+ (3596, 'ARMACAO DOS BUZIOS', 19, '3300233', 1),
+ (3597, 'ARRAIAL DO CABO', 19, '3300258', 1),
+ (3598, 'BARRA DO PIRAI', 19, '3300308', 1),
+ (3599, 'BARRA MANSA', 19, '3300407', 1),
+ (3600, 'BELFORD ROXO', 19, '3300456', 1),
+ (3601, 'BOM JARDIM', 19, '3300506', 1),
+ (3602, 'BOM JESUS DO ITABAPOANA', 19, '3300605', 1),
+ (3603, 'CABO FRIO', 19, '3300704', 1),
+ (3604, 'CACHOEIRAS DE MACACU', 19, '3300803', 1),
+ (3605, 'CAMBUCI', 19, '3300902', 1),
+ (3606, 'CARAPEBUS', 19, '3300936', 1),
+ (3607, 'COMENDADOR LEVY GASPARIAN', 19, '3300951', 1),
+ (3608, 'CAMPOS DOS GOYTACAZES', 19, '3301009', 1),
+ (3609, 'CANTAGALO', 19, '3301108', 1),
+ (3610, 'CARDOSO MOREIRA', 19, '3301157', 1),
+ (3611, 'CARMO', 19, '3301207', 1),
+ (3612, 'CASIMIRO DE ABREU', 19, '3301306', 1),
+ (3613, 'CONCEICAO DE MACABU', 19, '3301405', 1),
+ (3614, 'CORDEIRO', 19, '3301504', 1),
+ (3615, 'DUAS BARRAS', 19, '3301603', 1),
+ (3616, 'DUQUE DE CAXIAS', 19, '3301702', 1),
+ (3617, 'ENGENHEIRO PAULO DE FRONTIN', 19, '3301801', 1),
+ (3618, 'GUAPIMIRIM', 19, '3301850', 1),
+ (3619, 'IGUABA GRANDE', 19, '3301876', 1),
+ (3620, 'ITABORAI', 19, '3301900', 1),
+ (3621, 'ITAGUAI', 19, '3302007', 1),
+ (3622, 'ITALVA', 19, '3302056', 1),
+ (3623, 'ITAOCARA', 19, '3302106', 1),
+ (3624, 'ITAPERUNA', 19, '3302205', 1),
+ (3625, 'ITATIAIA', 19, '3302254', 1),
+ (3626, 'JAPERI', 19, '3302270', 1),
+ (3627, 'LAJE DO MURIAE', 19, '3302304', 1),
+ (3628, 'MACAE', 19, '3302403', 1),
+ (3629, 'MACUCO', 19, '3302452', 1),
+ (3630, 'MAGE', 19, '3302502', 1),
+ (3631, 'MANGARATIBA', 19, '3302601', 1),
+ (3632, 'MARICA', 19, '3302700', 1),
+ (3633, 'MENDES', 19, '3302809', 1),
+ (3634, 'MESQUITA', 19, '3302858', 1),
+ (3635, 'MIGUEL PEREIRA', 19, '3302908', 1),
+ (3636, 'MIRACEMA', 19, '3303005', 1),
+ (3637, 'NATIVIDADE', 19, '3303104', 1),
+ (3638, 'NILOPOLIS', 19, '3303203', 1),
+ (3639, 'NITEROI', 19, '3303302', 1),
+ (3640, 'NOVA FRIBURGO', 19, '3303401', 1),
+ (3641, 'NOVA IGUACU', 19, '3303500', 1),
+ (3642, 'PARACAMBI', 19, '3303609', 1),
+ (3643, 'PARAIBA DO SUL', 19, '3303708', 1),
+ (3644, 'PARATY', 19, '3303807', 1),
+ (3645, 'PATY DO ALFERES', 19, '3303856', 1),
+ (3646, 'PETROPOLIS', 19, '3303906', 1),
+ (3647, 'PINHEIRAL', 19, '3303955', 1),
+ (3648, 'PIRAI', 19, '3304003', 1),
+ (3649, 'PORCIUNCULA', 19, '3304102', 1),
+ (3650, 'PORTO REAL', 19, '3304110', 1),
+ (3651, 'QUATIS', 19, '3304128', 1),
+ (3652, 'QUEIMADOS', 19, '3304144', 1),
+ (3653, 'QUISSAMA', 19, '3304151', 1),
+ (3654, 'RESENDE', 19, '3304201', 1),
+ (3655, 'RIO BONITO', 19, '3304300', 1),
+ (3656, 'RIO CLARO', 19, '3304409', 1),
+ (3657, 'RIO DAS FLORES', 19, '3304508', 1),
+ (3658, 'RIO DAS OSTRAS', 19, '3304524', 1),
+ (3659, 'RIO DE JANEIRO', 19, '3304557', 1),
+ (3660, 'SANTA MARIA MADALENA', 19, '3304607', 1),
+ (3661, 'SANTO ANTONIO DE PADUA', 19, '3304706', 1),
+ (3662, 'SAO FRANCISCO DE ITABAPOANA', 19, '3304755', 1),
+ (3663, 'SAO FIDELIS', 19, '3304805', 1),
+ (3664, 'SAO GONCALO', 19, '3304904', 1),
+ (3665, 'SAO JOAO DA BARRA', 19, '3305000', 1),
+ (3666, 'SAO JOAO DE MERITI', 19, '3305109', 1),
+ (3667, 'SAO JOSE DE UBA', 19, '3305133', 1),
+ (3668, 'SAO JOSE DO VALE DO RIO PRETO', 19, '3305158', 1),
+ (3669, 'SAO PEDRO DA ALDEIA', 19, '3305208', 1),
+ (3670, 'SAO SEBASTIAO DO ALTO', 19, '3305307', 1),
+ (3671, 'SAPUCAIA', 19, '3305406', 1),
+ (3672, 'SAQUAREMA', 19, '3305505', 1),
+ (3673, 'SEROPEDICA', 19, '3305554', 1),
+ (3674, 'SILVA JARDIM', 19, '3305604', 1),
+ (3675, 'SUMIDOURO', 19, '3305703', 1),
+ (3676, 'TANGUA', 19, '3305752', 1),
+ (3677, 'TERESOPOLIS', 19, '3305802', 1),
+ (3678, 'TRAJANO DE MORAES', 19, '3305901', 1),
+ (3679, 'TRES RIOS', 19, '3306008', 1),
+ (3680, 'VALENCA', 19, '3306107', 1),
+ (3681, 'VARRE-SAI', 19, '3306156', 1),
+ (3682, 'VASSOURAS', 19, '3306206', 1),
+ (3683, 'VOLTA REDONDA', 19, '3306305', 1),
+ (3684, 'ACARI', 20, '2400109', 1),
+ (3685, 'ACU', 20, '2400208', 1),
+ (3686, 'AFONSO BEZERRA', 20, '2400307', 1),
+ (3687, 'AGUA NOVA', 20, '2400406', 1),
+ (3688, 'ALEXANDRIA', 20, '2400505', 1),
+ (3689, 'ALMINO AFONSO', 20, '2400604', 1),
+ (3690, 'ALTO DO RODRIGUES', 20, '2400703', 1),
+ (3691, 'ANGICOS', 20, '2400802', 1),
+ (3692, 'ANTONIO MARTINS', 20, '2400901', 1),
+ (3693, 'APODI', 20, '2401008', 1),
+ (3694, 'AREIA BRANCA', 20, '2401107', 1),
+ (3695, 'ARES', 20, '2401206', 1),
+ (3696, 'AUGUSTO SEVERO', 20, '2401305', 1),
+ (3697, 'BAIA FORMOSA', 20, '2401404', 1),
+ (3698, 'BARAUNA', 20, '2401453', 1),
+ (3699, 'BARCELONA', 20, '2401503', 1),
+ (3700, 'BENTO FERNANDES', 20, '2401602', 1),
+ (3701, 'BODO', 20, '2401651', 1),
+ (3702, 'BOM JESUS', 20, '2401701', 1),
+ (3703, 'BREJINHO', 20, '2401800', 1),
+ (3704, 'CAICARA DO NORTE', 20, '2401859', 1),
+ (3705, 'CAICARA DO RIO DO VENTO', 20, '2401909', 1),
+ (3706, 'CAICO', 20, '2402006', 1),
+ (3707, 'CAMPO REDONDO', 20, '2402105', 1),
+ (3708, 'CANGUARETAMA', 20, '2402204', 1),
+ (3709, 'CARAUBAS', 20, '2402303', 1),
+ (3710, 'CARNAUBA DOS DANTAS', 20, '2402402', 1),
+ (3711, 'CARNAUBAIS', 20, '2402501', 1),
+ (3712, 'CEARA-MIRIM', 20, '2402600', 1),
+ (3713, 'CERRO CORA', 20, '2402709', 1),
+ (3714, 'CORONEL EZEQUIEL', 20, '2402808', 1),
+ (3715, 'CORONEL JOAO PESSOA', 20, '2402907', 1),
+ (3716, 'CRUZETA', 20, '2403004', 1),
+ (3717, 'CURRAIS NOVOS', 20, '2403103', 1),
+ (3718, 'DOUTOR SEVERIANO', 20, '2403202', 1),
+ (3719, 'PARNAMIRIM', 20, '2403251', 1),
+ (3720, 'ENCANTO', 20, '2403301', 1),
+ (3721, 'EQUADOR', 20, '2403400', 1),
+ (3722, 'ESPIRITO SANTO', 20, '2403509', 1),
+ (3723, 'EXTREMOZ', 20, '2403608', 1),
+ (3724, 'FELIPE GUERRA', 20, '2403707', 1),
+ (3725, 'FERNANDO PEDROZA', 20, '2403756', 1),
+ (3726, 'FLORANIA', 20, '2403806', 1),
+ (3727, 'FRANCISCO DANTAS', 20, '2403905', 1),
+ (3728, 'FRUTUOSO GOMES', 20, '2404002', 1),
+ (3729, 'GALINHOS', 20, '2404101', 1),
+ (3730, 'GOIANINHA', 20, '2404200', 1),
+ (3731, 'GOVERNADOR DIX-SEPT ROSADO', 20, '2404309', 1),
+ (3732, 'GROSSOS', 20, '2404408', 1),
+ (3733, 'GUAMARE', 20, '2404507', 1),
+ (3734, 'IELMO MARINHO', 20, '2404606', 1),
+ (3735, 'IPANGUACU', 20, '2404705', 1),
+ (3736, 'IPUEIRA', 20, '2404804', 1),
+ (3737, 'ITAJA', 20, '2404853', 1),
+ (3738, 'BOILERPLATE', 20, '2404903', 1),
+ (3739, 'JACANA', 20, '2405009', 1),
+ (3740, 'JANDAIRA', 20, '2405108', 1),
+ (3741, 'JANDUIS', 20, '2405207', 1),
+ (3742, 'JANUARIO CICCO', 20, '2405306', 1),
+ (3743, 'JAPI', 20, '2405405', 1),
+ (3744, 'JARDIM DE ANGICOS', 20, '2405504', 1),
+ (3745, 'JARDIM DE PIRANHAS', 20, '2405603', 1),
+ (3746, 'JARDIM DO SERIDO', 20, '2405702', 1),
+ (3747, 'JOAO CAMARA', 20, '2405801', 1),
+ (3748, 'JOAO DIAS', 20, '2405900', 1),
+ (3749, 'JOSE DA PENHA', 20, '2406007', 1),
+ (3750, 'JUCURUTU', 20, '2406106', 1),
+ (3751, 'JUNDIA', 20, '2406155', 1),
+ (3752, 'LAGOA DANTA', 20, '2406205', 1),
+ (3753, 'LAGOA DE PEDRAS', 20, '2406304', 1),
+ (3754, 'LAGOA DE VELHOS', 20, '2406403', 1),
+ (3755, 'LAGOA NOVA', 20, '2406502', 1),
+ (3756, 'LAGOA SALGADA', 20, '2406601', 1),
+ (3757, 'LAJES', 20, '2406700', 1),
+ (3758, 'LAJES PINTADAS', 20, '2406809', 1),
+ (3759, 'LUCRECIA', 20, '2406908', 1),
+ (3760, 'LUIS GOMES', 20, '2407005', 1),
+ (3761, 'MACAIBA', 20, '2407104', 1),
+ (3762, 'MACAU', 20, '2407203', 1),
+ (3763, 'MAJOR SALES', 20, '2407252', 1),
+ (3764, 'MARCELINO VIEIRA', 20, '2407302', 1),
+ (3765, 'MARTINS', 20, '2407401', 1),
+ (3766, 'MAXARANGUAPE', 20, '2407500', 1),
+ (3767, 'MESSIAS TARGINO', 20, '2407609', 1),
+ (3768, 'MONTANHAS', 20, '2407708', 1),
+ (3769, 'MONTE ALEGRE', 20, '2407807', 1),
+ (3770, 'MONTE DAS GAMELEIRAS', 20, '2407906', 1),
+ (3771, 'MOSSORO', 20, '2408003', 1),
+ (3772, 'NATAL', 20, '2408102', 1),
+ (3773, 'NISIA FLORESTA', 20, '2408201', 1),
+ (3774, 'NOVA CRUZ', 20, '2408300', 1),
+ (3775, 'OLHO-DAGUA DO BORGES', 20, '2408409', 1),
+ (3776, 'OURO BRANCO', 20, '2408508', 1),
+ (3777, 'PARANA', 20, '2408607', 1),
+ (3778, 'PARAU', 20, '2408706', 1),
+ (3779, 'PARAZINHO', 20, '2408805', 1),
+ (3780, 'PARELHAS', 20, '2408904', 1),
+ (3781, 'RIO DO FOGO', 20, '2408953', 1),
+ (3782, 'PASSA E FICA', 20, '2409100', 1),
+ (3783, 'PASSAGEM', 20, '2409209', 1),
+ (3784, 'PATU', 20, '2409308', 1),
+ (3785, 'SANTA MARIA', 20, '2409332', 1),
+ (3786, 'PAU DOS FERROS', 20, '2409407', 1),
+ (3787, 'PEDRA GRANDE', 20, '2409506', 1),
+ (3788, 'PEDRA PRETA', 20, '2409605', 1),
+ (3789, 'PEDRO AVELINO', 20, '2409704', 1),
+ (3790, 'PEDRO VELHO', 20, '2409803', 1),
+ (3791, 'PENDENCIAS', 20, '2409902', 1),
+ (3792, 'PILOES', 20, '2410009', 1),
+ (3793, 'POCO BRANCO', 20, '2410108', 1),
+ (3794, 'PORTALEGRE', 20, '2410207', 1),
+ (3795, 'PORTO DO MANGUE', 20, '2410256', 1),
+ (3796, 'PRESIDENTE JUSCELINO', 20, '2410306', 1),
+ (3797, 'PUREZA', 20, '2410405', 1),
+ (3798, 'RAFAEL FERNANDES', 20, '2410504', 1),
+ (3799, 'RAFAEL GODEIRO', 20, '2410603', 1),
+ (3800, 'RIACHO DA CRUZ', 20, '2410702', 1),
+ (3801, 'RIACHO DE SANTANA', 20, '2410801', 1),
+ (3802, 'RIACHUELO', 20, '2410900', 1),
+ (3803, 'RODOLFO FERNANDES', 20, '2411007', 1),
+ (3804, 'TIBAU', 20, '2411056', 1),
+ (3805, 'RUY BARBOSA', 20, '2411106', 1),
+ (3806, 'SANTA CRUZ', 20, '2411205', 1),
+ (3807, 'SANTANA DO MATOS', 20, '2411403', 1),
+ (3808, 'SANTANA DO SERIDO', 20, '2411429', 1),
+ (3809, 'SANTO ANTONIO', 20, '2411502', 1),
+ (3810, 'SAO BENTO DO NORTE', 20, '2411601', 1),
+ (3811, 'SAO BENTO DO TRAIRI', 20, '2411700', 1),
+ (3812, 'SAO FERNANDO', 20, '2411809', 1),
+ (3813, 'SAO FRANCISCO DO OESTE', 20, '2411908', 1),
+ (3814, 'SAO GONCALO DO AMARANTE', 20, '2412005', 1),
+ (3815, 'SAO JOAO DO SABUGI', 20, '2412104', 1),
+ (3816, 'SAO JOSE DE MIPIBU', 20, '2412203', 1),
+ (3817, 'SAO JOSE DO CAMPESTRE', 20, '2412302', 1),
+ (3818, 'SAO JOSE DO SERIDO', 20, '2412401', 1),
+ (3819, 'SAO MIGUEL', 20, '2412500', 1),
+ (3820, 'SAO MIGUEL DO GOSTOSO', 20, '2412559', 1),
+ (3821, 'SAO PAULO DO POTENGI', 20, '2412609', 1),
+ (3822, 'SAO PEDRO', 20, '2412708', 1),
+ (3823, 'SAO RAFAEL', 20, '2412807', 1),
+ (3824, 'SAO TOME', 20, '2412906', 1),
+ (3825, 'SAO VICENTE', 20, '2413003', 1),
+ (3826, 'SENADOR ELOI DE SOUZA', 20, '2413102', 1),
+ (3827, 'SENADOR GEORGINO AVELINO', 20, '2413201', 1),
+ (3828, 'SERRA DE SAO BENTO', 20, '2413300', 1),
+ (3829, 'SERRA DO MEL', 20, '2413359', 1),
+ (3830, 'SERRA NEGRA DO NORTE', 20, '2413409', 1),
+ (3831, 'SERRINHA', 20, '2413508', 1),
+ (3832, 'SERRINHA DOS PINTOS', 20, '2413557', 1),
+ (3833, 'SEVERIANO MELO', 20, '2413607', 1),
+ (3834, 'SITIO NOVO', 20, '2413706', 1),
+ (3835, 'TABOLEIRO GRANDE', 20, '2413805', 1),
+ (3836, 'TAIPU', 20, '2413904', 1),
+ (3837, 'TANGARA', 20, '2414001', 1),
+ (3838, 'TENENTE ANANIAS', 20, '2414100', 1),
+ (3839, 'TENENTE LAURENTINO CRUZ', 20, '2414159', 1),
+ (3840, 'TIBAU DO SUL', 20, '2414209', 1),
+ (3841, 'TIMBAUBA DOS BATISTAS', 20, '2414308', 1),
+ (3842, 'TOUROS', 20, '2414407', 1),
+ (3843, 'TRIUNFO POTIGUAR', 20, '2414456', 1),
+ (3844, 'UMARIZAL', 20, '2414506', 1),
+ (3845, 'UPANEMA', 20, '2414605', 1),
+ (3846, 'VARZEA', 20, '2414704', 1),
+ (3847, 'VENHA-VER', 20, '2414753', 1),
+ (3848, 'VERA CRUZ', 20, '2414803', 1),
+ (3849, 'VICOSA', 20, '2414902', 1),
+ (3850, 'VILA FLOR', 20, '2415008', 1),
+ (3851, 'ALTA FLORESTA DOESTE', 21, '1100015', 1),
+ (3852, 'ARIQUEMES', 21, '1100023', 1),
+ (3853, 'CABIXI', 21, '1100031', 1),
+ (3854, 'CACOAL', 21, '1100049', 1),
+ (3855, 'CEREJEIRAS', 21, '1100056', 1),
+ (3856, 'COLORADO DO OESTE', 21, '1100064', 1),
+ (3857, 'CORUMBIARA', 21, '1100072', 1),
+ (3858, 'COSTA MARQUES', 21, '1100080', 1),
+ (3859, 'ESPIGAO DOESTE', 21, '1100098', 1),
+ (3860, 'GUAJARA-MIRIM', 21, '1100106', 1),
+ (3861, 'JARU', 21, '1100114', 1),
+ (3862, 'JI-PARANA', 21, '1100122', 1),
+ (3863, 'MACHADINHO DOESTE', 21, '1100130', 1),
+ (3864, 'NOVA BRASILANDIA DOESTE', 21, '1100148', 1),
+ (3865, 'OURO PRETO DO OESTE', 21, '1100155', 1),
+ (3866, 'PIMENTA BUENO', 21, '1100189', 1),
+ (3867, 'PORTO VELHO', 21, '1100205', 1),
+ (3868, 'PRESIDENTE MEDICI', 21, '1100254', 1),
+ (3869, 'RIO CRESPO', 21, '1100262', 1),
+ (3870, 'ROLIM DE MOURA', 21, '1100288', 1),
+ (3871, 'SANTA LUZIA DOESTE', 21, '1100296', 1),
+ (3872, 'VILHENA', 21, '1100304', 1),
+ (3873, 'SAO MIGUEL DO GUAPORE', 21, '1100320', 1),
+ (3874, 'NOVA MAMORE', 21, '1100338', 1),
+ (3875, 'ALVORADA DOESTE', 21, '1100346', 1),
+ (3876, 'ALTO ALEGRE DOS PARECIS', 21, '1100379', 1),
+ (3877, 'ALTO PARAISO', 21, '1100403', 1),
+ (3878, 'BURITIS', 21, '1100452', 1),
+ (3879, 'NOVO HORIZONTE DO OESTE', 21, '1100502', 1),
+ (3880, 'CACAULANDIA', 21, '1100601', 1),
+ (3881, 'CAMPO NOVO DE RONDONIA', 21, '1100700', 1),
+ (3882, 'CANDEIAS DO JAMARI', 21, '1100809', 1),
+ (3883, 'CASTANHEIRAS', 21, '1100908', 1),
+ (3884, 'CHUPINGUAIA', 21, '1100924', 1),
+ (3885, 'CUJUBIM', 21, '1100940', 1),
+ (3886, 'GOVERNADOR JORGE TEIXEIRA', 21, '1101005', 1),
+ (3887, 'ITAPUA DO OESTE', 21, '1101104', 1),
+ (3888, 'MINISTRO ANDREAZZA', 21, '1101203', 1),
+ (3889, 'MIRANTE DA SERRA', 21, '1101302', 1),
+ (3890, 'MONTE NEGRO', 21, '1101401', 1),
+ (3891, 'NOVA UNIAO', 21, '1101435', 1),
+ (3892, 'PARECIS', 21, '1101450', 1),
+ (3893, 'PIMENTEIRAS DO OESTE', 21, '1101468', 1),
+ (3894, 'PRIMAVERA DE RONDONIA', 21, '1101476', 1),
+ (3895, 'SAO FELIPE DOESTE', 21, '1101484', 1),
+ (3896, 'SAO FRANCISCO DO GUAPORE', 21, '1101492', 1),
+ (3897, 'SERINGUEIRAS', 21, '1101500', 1),
+ (3898, 'TEIXEIROPOLIS', 21, '1101559', 1),
+ (3899, 'THEOBROMA', 21, '1101609', 1),
+ (3900, 'URUPA', 21, '1101708', 1),
+ (3901, 'VALE DO ANARI', 21, '1101757', 1),
+ (3902, 'VALE DO PARAISO', 21, '1101807', 1),
+ (3903, 'AMAJARI', 22, '1400027', 1),
+ (3904, 'ALTO ALEGRE', 22, '1400050', 1),
+ (3905, 'BOA VISTA', 22, '1400100', 1),
+ (3906, 'BONFIM', 22, '1400159', 1),
+ (3907, 'CANTA', 22, '1400175', 1),
+ (3908, 'CARACARAI', 22, '1400209', 1),
+ (3909, 'CAROEBE', 22, '1400233', 1),
+ (3910, 'IRACEMA', 22, '1400282', 1),
+ (3911, 'MUCAJAI', 22, '1400308', 1),
+ (3912, 'NORMANDIA', 22, '1400407', 1),
+ (3913, 'PACARAIMA', 22, '1400456', 1),
+ (3914, 'RORAINOPOLIS', 22, '1400472', 1),
+ (3915, 'SAO JOAO DA BALIZA', 22, '1400506', 1),
+ (3916, 'SAO LUIZ', 22, '1400605', 1),
+ (3917, 'UIRAMUTA', 22, '1400704', 1),
+ (3918, 'ACEGUA', 23, '4300034', 1),
+ (3919, 'AGUA SANTA', 23, '4300059', 1),
+ (3920, 'AGUDO', 23, '4300109', 1),
+ (3921, 'AJURICABA', 23, '4300208', 1),
+ (3922, 'ALECRIM', 23, '4300307', 1),
+ (3923, 'ALEGRETE', 23, '4300406', 1),
+ (3924, 'ALEGRIA', 23, '4300455', 1),
+ (3925, 'ALMIRANTE TAMANDARE DO SUL', 23, '4300471', 1),
+ (3926, 'ALPESTRE', 23, '4300505', 1),
+ (3927, 'ALTO ALEGRE', 23, '4300554', 1),
+ (3928, 'ALTO FELIZ', 23, '4300570', 1),
+ (3929, 'ALVORADA', 23, '4300604', 1),
+ (3930, 'AMARAL FERRADOR', 23, '4300638', 1),
+ (3931, 'AMETISTA DO SUL', 23, '4300646', 1),
+ (3932, 'ANDRE DA ROCHA', 23, '4300661', 1),
+ (3933, 'ANTA GORDA', 23, '4300703', 1),
+ (3934, 'ANTONIO PRADO', 23, '4300802', 1),
+ (3935, 'ARAMBARE', 23, '4300851', 1),
+ (3936, 'ARARICA', 23, '4300877', 1),
+ (3937, 'ARATIBA', 23, '4300901', 1),
+ (3938, 'ARROIO DO MEIO', 23, '4301008', 1),
+ (3939, 'ARROIO DO SAL', 23, '4301057', 1),
+ (3940, 'ARROIO DO PADRE', 23, '4301073', 1),
+ (3941, 'ARROIO DOS RATOS', 23, '4301107', 1),
+ (3942, 'ARROIO DO TIGRE', 23, '4301206', 1),
+ (3943, 'ARROIO GRANDE', 23, '4301305', 1),
+ (3944, 'ARVOREZINHA', 23, '4301404', 1),
+ (3945, 'AUGUSTO PESTANA', 23, '4301503', 1),
+ (3946, 'AUREA', 23, '4301552', 1),
+ (3947, 'BAGE', 23, '4301602', 1),
+ (3948, 'BALNEARIO PINHAL', 23, '4301636', 1),
+ (3949, 'BARAO', 23, '4301651', 1),
+ (3950, 'BARAO DE COTEGIPE', 23, '4301701', 1),
+ (3951, 'BARAO DO TRIUNFO', 23, '4301750', 1),
+ (3952, 'BARRACAO', 23, '4301800', 1),
+ (3953, 'BARRA DO GUARITA', 23, '4301859', 1),
+ (3954, 'BARRA DO QUARAI', 23, '4301875', 1),
+ (3955, 'BARRA DO RIBEIRO', 23, '4301909', 1),
+ (3956, 'BARRA DO RIO AZUL', 23, '4301925', 1),
+ (3957, 'BARRA FUNDA', 23, '4301958', 1),
+ (3958, 'BARROS CASSAL', 23, '4302006', 1),
+ (3959, 'BENJAMIN CONSTANT DO SUL', 23, '4302055', 1),
+ (3960, 'BENTO GONCALVES', 23, '4302105', 1),
+ (3961, 'BOA VISTA DAS MISSOES', 23, '4302154', 1),
+ (3962, 'BOA VISTA DO BURICA', 23, '4302204', 1),
+ (3963, 'BOA VISTA DO CADEADO', 23, '4302220', 1),
+ (3964, 'BOA VISTA DO INCRA', 23, '4302238', 1),
+ (3965, 'BOA VISTA DO SUL', 23, '4302253', 1),
+ (3966, 'BOM JESUS', 23, '4302303', 1),
+ (3967, 'BOM PRINCIPIO', 23, '4302352', 1),
+ (3968, 'BOM PROGRESSO', 23, '4302378', 1),
+ (3969, 'BOM RETIRO DO SUL', 23, '4302402', 1),
+ (3970, 'BOQUEIRAO DO LEAO', 23, '4302451', 1),
+ (3971, 'BOSSOROCA', 23, '4302501', 1),
+ (3972, 'BOZANO', 23, '4302584', 1),
+ (3973, 'BRAGA', 23, '4302600', 1),
+ (3974, 'BROCHIER', 23, '4302659', 1),
+ (3975, 'BUTIA', 23, '4302709', 1),
+ (3976, 'CACAPAVA DO SUL', 23, '4302808', 1),
+ (3977, 'CACEQUI', 23, '4302907', 1),
+ (3978, 'CACHOEIRA DO SUL', 23, '4303004', 1),
+ (3979, 'CACHOEIRINHA', 23, '4303103', 1),
+ (3980, 'CACIQUE DOBLE', 23, '4303202', 1),
+ (3981, 'CAIBATE', 23, '4303301', 1),
+ (3982, 'CAICARA', 23, '4303400', 1),
+ (3983, 'CAMAQUA', 23, '4303509', 1),
+ (3984, 'CAMARGO', 23, '4303558', 1),
+ (3985, 'CAMBARA DO SUL', 23, '4303608', 1),
+ (3986, 'CAMPESTRE DA SERRA', 23, '4303673', 1),
+ (3987, 'CAMPINA DAS MISSOES', 23, '4303707', 1),
+ (3988, 'CAMPINAS DO SUL', 23, '4303806', 1),
+ (3989, 'CAMPO BOM', 23, '4303905', 1),
+ (3990, 'CAMPO NOVO', 23, '4304002', 1),
+ (3991, 'CAMPOS BORGES', 23, '4304101', 1),
+ (3992, 'CANDELARIA', 23, '4304200', 1),
+ (3993, 'CANDIDO GODOI', 23, '4304309', 1),
+ (3994, 'CANDIOTA', 23, '4304358', 1),
+ (3995, 'CANELA', 23, '4304408', 1),
+ (3996, 'CANGUCU', 23, '4304507', 1),
+ (3997, 'CANOAS', 23, '4304606', 1),
+ (3998, 'CANUDOS DO VALE', 23, '4304614', 1),
+ (3999, 'CAPAO BONITO DO SUL', 23, '4304622', 1),
+ (4000, 'CAPAO DA CANOA', 23, '4304630', 1),
+ (4001, 'CAPAO DO CIPO', 23, '4304655', 1),
+ (4002, 'CAPAO DO LEAO', 23, '4304663', 1),
+ (4003, 'CAPIVARI DO SUL', 23, '4304671', 1),
+ (4004, 'CAPELA DE SANTANA', 23, '4304689', 1),
+ (4005, 'CAPITAO', 23, '4304697', 1),
+ (4006, 'CARAZINHO', 23, '4304705', 1),
+ (4007, 'CARAA', 23, '4304713', 1),
+ (4008, 'CARLOS BARBOSA', 23, '4304804', 1),
+ (4009, 'CARLOS GOMES', 23, '4304853', 1),
+ (4010, 'CASCA', 23, '4304903', 1),
+ (4011, 'CASEIROS', 23, '4304952', 1),
+ (4012, 'CATUIPE', 23, '4305009', 1),
+ (4013, 'CAXIAS DO SUL', 23, '4305108', 1),
+ (4014, 'CENTENARIO', 23, '4305116', 1),
+ (4015, 'CERRITO', 23, '4305124', 1),
+ (4016, 'CERRO BRANCO', 23, '4305132', 1),
+ (4017, 'CERRO GRANDE', 23, '4305157', 1),
+ (4018, 'CERRO GRANDE DO SUL', 23, '4305173', 1),
+ (4019, 'CERRO LARGO', 23, '4305207', 1),
+ (4020, 'CHAPADA', 23, '4305306', 1),
+ (4021, 'CHARQUEADAS', 23, '4305355', 1),
+ (4022, 'CHARRUA', 23, '4305371', 1),
+ (4023, 'CHIAPETTA', 23, '4305405', 1),
+ (4024, 'CHUI', 23, '4305439', 1),
+ (4025, 'CHUVISCA', 23, '4305447', 1),
+ (4026, 'CIDREIRA', 23, '4305454', 1),
+ (4027, 'CIRIACO', 23, '4305504', 1),
+ (4028, 'COLINAS', 23, '4305587', 1),
+ (4029, 'COLORADO', 23, '4305603', 1),
+ (4030, 'CONDOR', 23, '4305702', 1),
+ (4031, 'CONSTANTINA', 23, '4305801', 1),
+ (4032, 'COQUEIRO BAIXO', 23, '4305835', 1),
+ (4033, 'COQUEIROS DO SUL', 23, '4305850', 1),
+ (4034, 'CORONEL BARROS', 23, '4305871', 1),
+ (4035, 'CORONEL BICACO', 23, '4305900', 1),
+ (4036, 'CORONEL PILAR', 23, '4305934', 1),
+ (4037, 'COTIPORA', 23, '4305959', 1),
+ (4038, 'COXILHA', 23, '4305975', 1),
+ (4039, 'CRISSIUMAL', 23, '4306007', 1),
+ (4040, 'CRISTAL', 23, '4306056', 1),
+ (4041, 'CRISTAL DO SUL', 23, '4306072', 1),
+ (4042, 'CRUZ ALTA', 23, '4306106', 1),
+ (4043, 'CRUZALTENSE', 23, '4306130', 1),
+ (4044, 'CRUZEIRO DO SUL', 23, '4306205', 1),
+ (4045, 'DAVID CANABARRO', 23, '4306304', 1),
+ (4046, 'DERRUBADAS', 23, '4306320', 1),
+ (4047, 'DEZESSEIS DE NOVEMBRO', 23, '4306353', 1),
+ (4048, 'DILERMANDO DE AGUIAR', 23, '4306379', 1),
+ (4049, 'DOIS IRMAOS', 23, '4306403', 1),
+ (4050, 'DOIS IRMAOS DAS MISSOES', 23, '4306429', 1),
+ (4051, 'DOIS LAJEADOS', 23, '4306452', 1),
+ (4052, 'DOM FELICIANO', 23, '4306502', 1),
+ (4053, 'DOM PEDRO DE ALCANTARA', 23, '4306551', 1),
+ (4054, 'DOM PEDRITO', 23, '4306601', 1),
+ (4055, 'DONA FRANCISCA', 23, '4306700', 1),
+ (4056, 'DOUTOR MAURICIO CARDOSO', 23, '4306734', 1),
+ (4057, 'DOUTOR RICARDO', 23, '4306759', 1),
+ (4058, 'ELDORADO DO SUL', 23, '4306767', 1),
+ (4059, 'ENCANTADO', 23, '4306809', 1),
+ (4060, 'ENCRUZILHADA DO SUL', 23, '4306908', 1),
+ (4061, 'ENGENHO VELHO', 23, '4306924', 1),
+ (4062, 'ENTRE-IJUIS', 23, '4306932', 1),
+ (4063, 'ENTRE RIOS DO SUL', 23, '4306957', 1),
+ (4064, 'EREBANGO', 23, '4306973', 1),
+ (4065, 'ERECHIM', 23, '4307005', 1),
+ (4066, 'ERNESTINA', 23, '4307054', 1),
+ (4067, 'HERVAL', 23, '4307104', 1),
+ (4068, 'ERVAL GRANDE', 23, '4307203', 1),
+ (4069, 'ERVAL SECO', 23, '4307302', 1),
+ (4070, 'ESMERALDA', 23, '4307401', 1),
+ (4071, 'ESPERANCA DO SUL', 23, '4307450', 1),
+ (4072, 'ESPUMOSO', 23, '4307500', 1),
+ (4073, 'ESTACAO', 23, '4307559', 1),
+ (4074, 'ESTANCIA VELHA', 23, '4307609', 1),
+ (4075, 'ESTEIO', 23, '4307708', 1),
+ (4076, 'ESTRELA', 23, '4307807', 1),
+ (4077, 'ESTRELA VELHA', 23, '4307815', 1),
+ (4078, 'EUGENIO DE CASTRO', 23, '4307831', 1),
+ (4079, 'FAGUNDES VARELA', 23, '4307864', 1),
+ (4080, 'FARROUPILHA', 23, '4307906', 1),
+ (4081, 'FAXINAL DO SOTURNO', 23, '4308003', 1),
+ (4082, 'FAXINALZINHO', 23, '4308052', 1),
+ (4083, 'FAZENDA VILANOVA', 23, '4308078', 1),
+ (4084, 'FELIZ', 23, '4308102', 1),
+ (4085, 'FLORES DA CUNHA', 23, '4308201', 1),
+ (4086, 'FLORIANO PEIXOTO', 23, '4308250', 1),
+ (4087, 'FONTOURA XAVIER', 23, '4308300', 1),
+ (4088, 'FORMIGUEIRO', 23, '4308409', 1),
+ (4089, 'FORQUETINHA', 23, '4308433', 1),
+ (4090, 'FORTALEZA DOS VALOS', 23, '4308458', 1),
+ (4091, 'FREDERICO WESTPHALEN', 23, '4308508', 1),
+ (4092, 'GARIBALDI', 23, '4308607', 1),
+ (4093, 'GARRUCHOS', 23, '4308656', 1),
+ (4094, 'GAURAMA', 23, '4308706', 1),
+ (4095, 'GENERAL CAMARA', 23, '4308805', 1),
+ (4096, 'GENTIL', 23, '4308854', 1),
+ (4097, 'GETULIO VARGAS', 23, '4308904', 1),
+ (4098, 'GIRUA', 23, '4309001', 1),
+ (4099, 'GLORINHA', 23, '4309050', 1),
+ (4100, 'GRAMADO', 23, '4309100', 1),
+ (4101, 'GRAMADO DOS LOUREIROS', 23, '4309126', 1),
+ (4102, 'GRAMADO XAVIER', 23, '4309159', 1),
+ (4103, 'GRAVATAI', 23, '4309209', 1),
+ (4104, 'GUABIJU', 23, '4309258', 1),
+ (4105, 'GUAIBA', 23, '4309308', 1),
+ (4106, 'GUAPORE', 23, '4309407', 1),
+ (4107, 'GUARANI DAS MISSOES', 23, '4309506', 1),
+ (4108, 'HARMONIA', 23, '4309555', 1),
+ (4109, 'HERVEIRAS', 23, '4309571', 1),
+ (4110, 'HORIZONTINA', 23, '4309605', 1),
+ (4111, 'HULHA NEGRA', 23, '4309654', 1),
+ (4112, 'HUMAITA', 23, '4309704', 1),
+ (4113, 'IBARAMA', 23, '4309753', 1),
+ (4114, 'IBIACA', 23, '4309803', 1),
+ (4115, 'IBIRAIARAS', 23, '4309902', 1),
+ (4116, 'IBIRAPUITA', 23, '4309951', 1),
+ (4117, 'IBIRUBA', 23, '4310009', 1),
+ (4118, 'IGREJINHA', 23, '4310108', 1),
+ (4119, 'IJUI', 23, '4310207', 1),
+ (4120, 'ILOPOLIS', 23, '4310306', 1),
+ (4121, 'IMBE', 23, '4310330', 1),
+ (4122, 'IMIGRANTE', 23, '4310363', 1),
+ (4123, 'INDEPENDENCIA', 23, '4310405', 1),
+ (4124, 'INHACORA', 23, '4310413', 1),
+ (4125, 'IPE', 23, '4310439', 1),
+ (4126, 'IPIRANGA DO SUL', 23, '4310462', 1),
+ (4127, 'IRAI', 23, '4310504', 1),
+ (4128, 'ITAARA', 23, '4310538', 1),
+ (4129, 'ITACURUBI', 23, '4310553', 1),
+ (4130, 'ITAPUCA', 23, '4310579', 1),
+ (4131, 'ITAQUI', 23, '4310603', 1),
+ (4132, 'ITATI', 23, '4310652', 1),
+ (4133, 'ITATIBA DO SUL', 23, '4310702', 1),
+ (4134, 'IVORA', 23, '4310751', 1),
+ (4135, 'IVOTI', 23, '4310801', 1),
+ (4136, 'JABOTICABA', 23, '4310850', 1),
+ (4137, 'JACUIZINHO', 23, '4310876', 1),
+ (4138, 'JACUTINGA', 23, '4310900', 1),
+ (4139, 'JAGUARAO', 23, '4311007', 1),
+ (4140, 'JAGUARI', 23, '4311106', 1),
+ (4141, 'JAQUIRANA', 23, '4311122', 1),
+ (4142, 'JARI', 23, '4311130', 1),
+ (4143, 'JOIA', 23, '4311155', 1),
+ (4144, 'JULIO DE CASTILHOS', 23, '4311205', 1),
+ (4145, 'LAGOA BONITA DO SUL', 23, '4311239', 1),
+ (4146, 'LAGOAO', 23, '4311254', 1),
+ (4147, 'LAGOA DOS TRES CANTOS', 23, '4311270', 1),
+ (4148, 'LAGOA VERMELHA', 23, '4311304', 1),
+ (4149, 'LAJEADO', 23, '4311403', 1),
+ (4150, 'LAJEADO DO BUGRE', 23, '4311429', 1),
+ (4151, 'LAVRAS DO SUL', 23, '4311502', 1),
+ (4152, 'LIBERATO SALZANO', 23, '4311601', 1),
+ (4153, 'LINDOLFO COLLOR', 23, '4311627', 1),
+ (4154, 'LINHA NOVA', 23, '4311643', 1),
+ (4155, 'MACHADINHO', 23, '4311700', 1),
+ (4156, 'MACAMBARA', 23, '4311718', 1),
+ (4157, 'MAMPITUBA', 23, '4311734', 1),
+ (4158, 'MANOEL VIANA', 23, '4311759', 1),
+ (4159, 'MAQUINE', 23, '4311775', 1),
+ (4160, 'MARATA', 23, '4311791', 1),
+ (4161, 'MARAU', 23, '4311809', 1),
+ (4162, 'MARCELINO RAMOS', 23, '4311908', 1),
+ (4163, 'MARIANA PIMENTEL', 23, '4311981', 1),
+ (4164, 'MARIANO MORO', 23, '4312005', 1),
+ (4165, 'MARQUES DE SOUZA', 23, '4312054', 1),
+ (4166, 'MATA', 23, '4312104', 1),
+ (4167, 'MATO CASTELHANO', 23, '4312138', 1),
+ (4168, 'MATO LEITAO', 23, '4312153', 1),
+ (4169, 'MATO QUEIMADO', 23, '4312179', 1),
+ (4170, 'MAXIMILIANO DE ALMEIDA', 23, '4312203', 1),
+ (4171, 'MINAS DO LEAO', 23, '4312252', 1),
+ (4172, 'MIRAGUAI', 23, '4312302', 1),
+ (4173, 'MONTAURI', 23, '4312351', 1),
+ (4174, 'MONTE ALEGRE DOS CAMPOS', 23, '4312377', 1),
+ (4175, 'MONTE BELO DO SUL', 23, '4312385', 1),
+ (4176, 'MONTENEGRO', 23, '4312401', 1),
+ (4177, 'MORMACO', 23, '4312427', 1),
+ (4178, 'MORRINHOS DO SUL', 23, '4312443', 1),
+ (4179, 'MORRO REDONDO', 23, '4312450', 1),
+ (4180, 'MORRO REUTER', 23, '4312476', 1),
+ (4181, 'MOSTARDAS', 23, '4312500', 1),
+ (4182, 'MUCUM', 23, '4312609', 1),
+ (4183, 'MUITOS CAPOES', 23, '4312617', 1),
+ (4184, 'MULITERNO', 23, '4312625', 1),
+ (4185, 'NAO-ME-TOQUE', 23, '4312658', 1),
+ (4186, 'NICOLAU VERGUEIRO', 23, '4312674', 1),
+ (4187, 'NONOAI', 23, '4312708', 1),
+ (4188, 'NOVA ALVORADA', 23, '4312757', 1),
+ (4189, 'NOVA ARACA', 23, '4312807', 1),
+ (4190, 'NOVA BASSANO', 23, '4312906', 1),
+ (4191, 'NOVA BOA VISTA', 23, '4312955', 1),
+ (4192, 'NOVA BRESCIA', 23, '4313003', 1),
+ (4193, 'NOVA CANDELARIA', 23, '4313011', 1),
+ (4194, 'NOVA ESPERANCA DO SUL', 23, '4313037', 1),
+ (4195, 'NOVA HARTZ', 23, '4313060', 1),
+ (4196, 'NOVA PADUA', 23, '4313086', 1),
+ (4197, 'NOVA PALMA', 23, '4313102', 1),
+ (4198, 'NOVA PETROPOLIS', 23, '4313201', 1),
+ (4199, 'NOVA PRATA', 23, '4313300', 1),
+ (4200, 'NOVA RAMADA', 23, '4313334', 1),
+ (4201, 'NOVA ROMA DO SUL', 23, '4313359', 1),
+ (4202, 'NOVA SANTA RITA', 23, '4313375', 1),
+ (4203, 'NOVO CABRAIS', 23, '4313391', 1),
+ (4204, 'NOVO HAMBURGO', 23, '4313409', 1),
+ (4205, 'NOVO MACHADO', 23, '4313425', 1),
+ (4206, 'NOVO TIRADENTES', 23, '4313441', 1),
+ (4207, 'NOVO XINGU', 23, '4313466', 1),
+ (4208, 'NOVO BARREIRO', 23, '4313490', 1),
+ (4209, 'OSORIO', 23, '4313508', 1),
+ (4210, 'PAIM FILHO', 23, '4313607', 1),
+ (4211, 'PALMARES DO SUL', 23, '4313656', 1),
+ (4212, 'PALMEIRA DAS MISSOES', 23, '4313706', 1),
+ (4213, 'PALMITINHO', 23, '4313805', 1),
+ (4214, 'PANAMBI', 23, '4313904', 1),
+ (4215, 'PANTANO GRANDE', 23, '4313953', 1),
+ (4216, 'PARAI', 23, '4314001', 1),
+ (4217, 'PARAISO DO SUL', 23, '4314027', 1),
+ (4218, 'PARECI NOVO', 23, '4314035', 1),
+ (4219, 'PAROBE', 23, '4314050', 1),
+ (4220, 'PASSA SETE', 23, '4314068', 1),
+ (4221, 'PASSO DO SOBRADO', 23, '4314076', 1),
+ (4222, 'PASSO FUNDO', 23, '4314100', 1),
+ (4223, 'PAULO BENTO', 23, '4314134', 1),
+ (4224, 'PAVERAMA', 23, '4314159', 1),
+ (4225, 'PEDRAS ALTAS', 23, '4314175', 1),
+ (4226, 'PEDRO OSORIO', 23, '4314209', 1),
+ (4227, 'PEJUCARA', 23, '4314308', 1),
+ (4228, 'PELOTAS', 23, '4314407', 1),
+ (4229, 'PICADA CAFE', 23, '4314423', 1),
+ (4230, 'PINHAL', 23, '4314456', 1),
+ (4231, 'PINHAL DA SERRA', 23, '4314464', 1),
+ (4232, 'PINHAL GRANDE', 23, '4314472', 1),
+ (4233, 'PINHEIRINHO DO VALE', 23, '4314498', 1),
+ (4234, 'PINHEIRO MACHADO', 23, '4314506', 1),
+ (4235, 'PIRAPO', 23, '4314555', 1),
+ (4236, 'PIRATINI', 23, '4314605', 1),
+ (4237, 'PLANALTO', 23, '4314704', 1),
+ (4238, 'POCO DAS ANTAS', 23, '4314753', 1),
+ (4239, 'PONTAO', 23, '4314779', 1),
+ (4240, 'PONTE PRETA', 23, '4314787', 1),
+ (4241, 'PORTAO', 23, '4314803', 1),
+ (4242, 'PORTO ALEGRE', 23, '4314902', 1),
+ (4243, 'PORTO LUCENA', 23, '4315008', 1),
+ (4244, 'PORTO MAUA', 23, '4315057', 1),
+ (4245, 'PORTO VERA CRUZ', 23, '4315073', 1),
+ (4246, 'PORTO XAVIER', 23, '4315107', 1),
+ (4247, 'POUSO NOVO', 23, '4315131', 1),
+ (4248, 'PRESIDENTE LUCENA', 23, '4315149', 1),
+ (4249, 'PROGRESSO', 23, '4315156', 1),
+ (4250, 'PROTASIO ALVES', 23, '4315172', 1),
+ (4251, 'PUTINGA', 23, '4315206', 1),
+ (4252, 'QUARAI', 23, '4315305', 1),
+ (4253, 'QUATRO IRMAOS', 23, '4315313', 1),
+ (4254, 'QUEVEDOS', 23, '4315321', 1),
+ (4255, 'QUINZE DE NOVEMBRO', 23, '4315354', 1),
+ (4256, 'REDENTORA', 23, '4315404', 1),
+ (4257, 'RELVADO', 23, '4315453', 1),
+ (4258, 'RESTINGA SECA', 23, '4315503', 1),
+ (4259, 'RIO DOS INDIOS', 23, '4315552', 1),
+ (4260, 'RIO GRANDE', 23, '4315602', 1),
+ (4261, 'RIO PARDO', 23, '4315701', 1),
+ (4262, 'RIOZINHO', 23, '4315750', 1),
+ (4263, 'ROCA SALES', 23, '4315800', 1),
+ (4264, 'RODEIO BONITO', 23, '4315909', 1),
+ (4265, 'ROLADOR', 23, '4315958', 1),
+ (4266, 'ROLANTE', 23, '4316006', 1),
+ (4267, 'RONDA ALTA', 23, '4316105', 1),
+ (4268, 'RONDINHA', 23, '4316204', 1),
+ (4269, 'ROQUE GONZALES', 23, '4316303', 1),
+ (4270, 'ROSARIO DO SUL', 23, '4316402', 1),
+ (4271, 'SAGRADA FAMILIA', 23, '4316428', 1),
+ (4272, 'SALDANHA MARINHO', 23, '4316436', 1),
+ (4273, 'SALTO DO JACUI', 23, '4316451', 1),
+ (4274, 'SALVADOR DAS MISSOES', 23, '4316477', 1),
+ (4275, 'SALVADOR DO SUL', 23, '4316501', 1),
+ (4276, 'SANANDUVA', 23, '4316600', 1),
+ (4277, 'SANTA BARBARA DO SUL', 23, '4316709', 1),
+ (4278, 'SANTA CECILIA DO SUL', 23, '4316733', 1),
+ (4279, 'SANTA CLARA DO SUL', 23, '4316758', 1),
+ (4280, 'SANTA CRUZ DO SUL', 23, '4316808', 1),
+ (4281, 'SANTA MARIA', 23, '4316907', 1),
+ (4282, 'SANTA MARIA DO HERVAL', 23, '4316956', 1),
+ (4283, 'SANTA MARGARIDA DO SUL', 23, '4316972', 1),
+ (4284, 'SANTANA DA BOA VISTA', 23, '4317004', 1),
+ (4285, 'SANTANA DO LIVRAMENTO', 23, '4317103', 1),
+ (4286, 'SANTA ROSA', 23, '4317202', 1),
+ (4287, 'SANTA TEREZA', 23, '4317251', 1),
+ (4288, 'SANTA VITORIA DO PALMAR', 23, '4317301', 1),
+ (4289, 'SANTIAGO', 23, '4317400', 1),
+ (4290, 'SANTO ANGELO', 23, '4317509', 1),
+ (4291, 'SANTO ANTONIO DO PALMA', 23, '4317558', 1),
+ (4292, 'SANTO ANTONIO DA PATRULHA', 23, '4317608', 1),
+ (4293, 'SANTO ANTONIO DAS MISSOES', 23, '4317707', 1),
+ (4294, 'SANTO ANTONIO DO PLANALTO', 23, '4317756', 1),
+ (4295, 'SANTO AUGUSTO', 23, '4317806', 1),
+ (4296, 'SANTO CRISTO', 23, '4317905', 1),
+ (4297, 'SANTO EXPEDITO DO SUL', 23, '4317954', 1),
+ (4298, 'SAO BORJA', 23, '4318002', 1),
+ (4299, 'SAO DOMINGOS DO SUL', 23, '4318051', 1),
+ (4300, 'SAO FRANCISCO DE ASSIS', 23, '4318101', 1),
+ (4301, 'SAO FRANCISCO DE PAULA', 23, '4318200', 1),
+ (4302, 'SAO GABRIEL', 23, '4318309', 1),
+ (4303, 'SAO JERONIMO', 23, '4318408', 1),
+ (4304, 'SAO JOAO DA URTIGA', 23, '4318424', 1),
+ (4305, 'SAO JOAO DO POLESINE', 23, '4318432', 1),
+ (4306, 'SAO JORGE', 23, '4318440', 1),
+ (4307, 'SAO JOSE DAS MISSOES', 23, '4318457', 1),
+ (4308, 'SAO JOSE DO HERVAL', 23, '4318465', 1),
+ (4309, 'SAO JOSE DO HORTENCIO', 23, '4318481', 1),
+ (4310, 'SAO JOSE DO INHACORA', 23, '4318499', 1),
+ (4311, 'SAO JOSE DO NORTE', 23, '4318507', 1),
+ (4312, 'SAO JOSE DO OURO', 23, '4318606', 1),
+ (4313, 'SAO JOSE DO SUL', 23, '4318614', 1),
+ (4314, 'SAO JOSE DOS AUSENTES', 23, '4318622', 1),
+ (4315, 'SAO LEOPOLDO', 23, '4318705', 1),
+ (4316, 'SAO LOURENCO DO SUL', 23, '4318804', 1),
+ (4317, 'SAO LUIZ GONZAGA', 23, '4318903', 1),
+ (4318, 'SAO MARCOS', 23, '4319000', 1),
+ (4319, 'SAO MARTINHO', 23, '4319109', 1),
+ (4320, 'SAO MARTINHO DA SERRA', 23, '4319125', 1),
+ (4321, 'SAO MIGUEL DAS MISSOES', 23, '4319158', 1),
+ (4322, 'SAO NICOLAU', 23, '4319208', 1),
+ (4323, 'SAO PAULO DAS MISSOES', 23, '4319307', 1),
+ (4324, 'SAO PEDRO DA SERRA', 23, '4319356', 1),
+ (4325, 'SAO PEDRO DAS MISSOES', 23, '4319364', 1),
+ (4326, 'SAO PEDRO DO BUTIA', 23, '4319372', 1),
+ (4327, 'SAO PEDRO DO SUL', 23, '4319406', 1),
+ (4328, 'SAO SEBASTIAO DO CAI', 23, '4319505', 1),
+ (4329, 'SAO SEPE', 23, '4319604', 1),
+ (4330, 'SAO VALENTIM', 23, '4319703', 1),
+ (4331, 'SAO VALENTIM DO SUL', 23, '4319711', 1),
+ (4332, 'SAO VALERIO DO SUL', 23, '4319737', 1),
+ (4333, 'SAO VENDELINO', 23, '4319752', 1),
+ (4334, 'SAO VICENTE DO SUL', 23, '4319802', 1),
+ (4335, 'SAPIRANGA', 23, '4319901', 1),
+ (4336, 'SAPUCAIA DO SUL', 23, '4320008', 1),
+ (4337, 'SARANDI', 23, '4320107', 1),
+ (4338, 'SEBERI', 23, '4320206', 1),
+ (4339, 'SEDE NOVA', 23, '4320230', 1),
+ (4340, 'SEGREDO', 23, '4320263', 1),
+ (4341, 'SELBACH', 23, '4320305', 1),
+ (4342, 'SENADOR SALGADO FILHO', 23, '4320321', 1),
+ (4343, 'SENTINELA DO SUL', 23, '4320354', 1),
+ (4344, 'SERAFINA CORREA', 23, '4320404', 1),
+ (4345, 'SERIO', 23, '4320453', 1),
+ (4346, 'SERTAO', 23, '4320503', 1),
+ (4347, 'SERTAO SANTANA', 23, '4320552', 1),
+ (4348, 'SETE DE SETEMBRO', 23, '4320578', 1),
+ (4349, 'SEVERIANO DE ALMEIDA', 23, '4320602', 1),
+ (4350, 'SILVEIRA MARTINS', 23, '4320651', 1),
+ (4351, 'SINIMBU', 23, '4320677', 1),
+ (4352, 'SOBRADINHO', 23, '4320701', 1),
+ (4353, 'SOLEDADE', 23, '4320800', 1),
+ (4354, 'TABAI', 23, '4320859', 1),
+ (4355, 'TAPEJARA', 23, '4320909', 1),
+ (4356, 'TAPERA', 23, '4321006', 1),
+ (4357, 'TAPES', 23, '4321105', 1),
+ (4358, 'TAQUARA', 23, '4321204', 1),
+ (4359, 'TAQUARI', 23, '4321303', 1),
+ (4360, 'TAQUARUCU DO SUL', 23, '4321329', 1),
+ (4361, 'TAVARES', 23, '4321352', 1),
+ (4362, 'TENENTE PORTELA', 23, '4321402', 1),
+ (4363, 'TERRA DE AREIA', 23, '4321436', 1),
+ (4364, 'TEUTONIA', 23, '4321451', 1),
+ (4365, 'TIO HUGO', 23, '4321469', 1),
+ (4366, 'TIRADENTES DO SUL', 23, '4321477', 1),
+ (4367, 'TOROPI', 23, '4321493', 1),
+ (4368, 'TORRES', 23, '4321501', 1),
+ (4369, 'TRAMANDAI', 23, '4321600', 1),
+ (4370, 'TRAVESSEIRO', 23, '4321626', 1),
+ (4371, 'TRES ARROIOS', 23, '4321634', 1),
+ (4372, 'TRES CACHOEIRAS', 23, '4321667', 1),
+ (4373, 'TRES COROAS', 23, '4321709', 1),
+ (4374, 'TRES DE MAIO', 23, '4321808', 1),
+ (4375, 'TRES FORQUILHAS', 23, '4321832', 1),
+ (4376, 'TRES PALMEIRAS', 23, '4321857', 1),
+ (4377, 'TRES PASSOS', 23, '4321907', 1),
+ (4378, 'TRINDADE DO SUL', 23, '4321956', 1),
+ (4379, 'TRIUNFO', 23, '4322004', 1),
+ (4380, 'TUCUNDUVA', 23, '4322103', 1),
+ (4381, 'TUNAS', 23, '4322152', 1),
+ (4382, 'TUPANCI DO SUL', 23, '4322186', 1),
+ (4383, 'TUPANCIRETA', 23, '4322202', 1),
+ (4384, 'TUPANDI', 23, '4322251', 1),
+ (4385, 'TUPARENDI', 23, '4322301', 1),
+ (4386, 'TURUCU', 23, '4322327', 1),
+ (4387, 'UBIRETAMA', 23, '4322343', 1),
+ (4388, 'UNIAO DA SERRA', 23, '4322350', 1),
+ (4389, 'UNISTALDA', 23, '4322376', 1),
+ (4390, 'URUGUAIANA', 23, '4322400', 1),
+ (4391, 'VACARIA', 23, '4322509', 1),
+ (4392, 'VALE VERDE', 23, '4322525', 1),
+ (4393, 'VALE DO SOL', 23, '4322533', 1),
+ (4394, 'VALE REAL', 23, '4322541', 1),
+ (4395, 'VANINI', 23, '4322558', 1),
+ (4396, 'VENANCIO AIRES', 23, '4322608', 1),
+ (4397, 'VERA CRUZ', 23, '4322707', 1),
+ (4398, 'VERANOPOLIS', 23, '4322806', 1),
+ (4399, 'VESPASIANO CORREA', 23, '4322855', 1),
+ (4400, 'VIADUTOS', 23, '4322905', 1),
+ (4401, 'VIAMAO', 23, '4323002', 1),
+ (4402, 'VICENTE DUTRA', 23, '4323101', 1),
+ (4403, 'VICTOR GRAEFF', 23, '4323200', 1),
+ (4404, 'VILA FLORES', 23, '4323309', 1),
+ (4405, 'VILA LANGARO', 23, '4323358', 1),
+ (4406, 'VILA MARIA', 23, '4323408', 1),
+ (4407, 'VILA NOVA DO SUL', 23, '4323457', 1),
+ (4408, 'VISTA ALEGRE', 23, '4323507', 1),
+ (4409, 'VISTA ALEGRE DO PRATA', 23, '4323606', 1),
+ (4410, 'VISTA GAUCHA', 23, '4323705', 1),
+ (4411, 'VITORIA DAS MISSOES', 23, '4323754', 1),
+ (4412, 'WESTFALIA', 23, '4323770', 1),
+ (4413, 'XANGRI-LA', 23, '4323804', 1),
+ (4414, 'ABDON BATISTA', 24, '4200051', 1),
+ (4415, 'ABELARDO LUZ', 24, '4200101', 1),
+ (4416, 'AGROLANDIA', 24, '4200200', 1),
+ (4417, 'AGRONOMICA', 24, '4200309', 1),
+ (4418, 'AGUA DOCE', 24, '4200408', 1),
+ (4419, 'AGUAS DE CHAPECO', 24, '4200507', 1),
+ (4420, 'AGUAS FRIAS', 24, '4200556', 1),
+ (4421, 'AGUAS MORNAS', 24, '4200606', 1),
+ (4422, 'ALFREDO WAGNER', 24, '4200705', 1),
+ (4423, 'ALTO BELA VISTA', 24, '4200754', 1),
+ (4424, 'ANCHIETA', 24, '4200804', 1),
+ (4425, 'ANGELINA', 24, '4200903', 1),
+ (4426, 'ANITA GARIBALDI', 24, '4201000', 1),
+ (4427, 'ANITAPOLIS', 24, '4201109', 1),
+ (4428, 'ANTONIO CARLOS', 24, '4201208', 1),
+ (4429, 'APIUNA', 24, '4201257', 1),
+ (4430, 'ARABUTA', 24, '4201273', 1),
+ (4431, 'ARAQUARI', 24, '4201307', 1),
+ (4432, 'ARARANGUA', 24, '4201406', 1),
+ (4433, 'ARMAZEM', 24, '4201505', 1),
+ (4434, 'ARROIO TRINTA', 24, '4201604', 1),
+ (4435, 'ARVOREDO', 24, '4201653', 1),
+ (4436, 'ASCURRA', 24, '4201703', 1),
+ (4437, 'ATALANTA', 24, '4201802', 1),
+ (4438, 'AURORA', 24, '4201901', 1),
+ (4439, 'BALNEARIO ARROIO DO SILVA', 24, '4201950', 1),
+ (4440, 'BALNEARIO CAMBORIU', 24, '4202008', 1),
+ (4441, 'BALNEARIO BARRA DO SUL', 24, '4202057', 1),
+ (4442, 'BALNEARIO GAIVOTA', 24, '4202073', 1),
+ (4443, 'BANDEIRANTE', 24, '4202081', 1),
+ (4444, 'BARRA BONITA', 24, '4202099', 1),
+ (4445, 'BARRA VELHA', 24, '4202107', 1),
+ (4446, 'BELA VISTA DO TOLDO', 24, '4202131', 1),
+ (4447, 'BELMONTE', 24, '4202156', 1),
+ (4448, 'BENEDITO NOVO', 24, '4202206', 1),
+ (4449, 'BIGUACU', 24, '4202305', 1),
+ (4450, 'BLUMENAU', 24, '4202404', 1),
+ (4451, 'BOCAINA DO SUL', 24, '4202438', 1),
+ (4452, 'BOMBINHAS', 24, '4202453', 1),
+ (4453, 'BOM JARDIM DA SERRA', 24, '4202503', 1),
+ (4454, 'BOM JESUS', 24, '4202537', 1),
+ (4455, 'BOM JESUS DO OESTE', 24, '4202578', 1),
+ (4456, 'BOM RETIRO', 24, '4202602', 1),
+ (4457, 'BOTUVERA', 24, '4202701', 1),
+ (4458, 'BRACO DO NORTE', 24, '4202800', 1),
+ (4459, 'BRACO DO TROMBUDO', 24, '4202859', 1),
+ (4460, 'BRUNOPOLIS', 24, '4202875', 1),
+ (4461, 'BRUSQUE', 24, '4202909', 1),
+ (4462, 'CACADOR', 24, '4203006', 1),
+ (4463, 'CAIBI', 24, '4203105', 1),
+ (4464, 'CALMON', 24, '4203154', 1),
+ (4465, 'CAMBORIU', 24, '4203204', 1),
+ (4466, 'CAPAO ALTO', 24, '4203253', 1),
+ (4467, 'CAMPO ALEGRE', 24, '4203303', 1),
+ (4468, 'CAMPO BELO DO SUL', 24, '4203402', 1),
+ (4469, 'CAMPO ERE', 24, '4203501', 1),
+ (4470, 'CAMPOS NOVOS', 24, '4203600', 1),
+ (4471, 'CANELINHA', 24, '4203709', 1),
+ (4472, 'CANOINHAS', 24, '4203808', 1),
+ (4473, 'CAPINZAL', 24, '4203907', 1),
+ (4474, 'CAPIVARI DE BAIXO', 24, '4203956', 1),
+ (4475, 'CATANDUVAS', 24, '4204004', 1),
+ (4476, 'CAXAMBU DO SUL', 24, '4204103', 1),
+ (4477, 'CELSO RAMOS', 24, '4204152', 1),
+ (4478, 'CERRO NEGRO', 24, '4204178', 1),
+ (4479, 'CHAPADAO DO LAGEADO', 24, '4204194', 1),
+ (4480, 'CHAPECO', 24, '4204202', 1),
+ (4481, 'COCAL DO SUL', 24, '4204251', 1),
+ (4482, 'CONCORDIA', 24, '4204301', 1),
+ (4483, 'CORDILHEIRA ALTA', 24, '4204350', 1),
+ (4484, 'CORONEL FREITAS', 24, '4204400', 1),
+ (4485, 'CORONEL MARTINS', 24, '4204459', 1),
+ (4486, 'CORUPA', 24, '4204509', 1),
+ (4487, 'CORREIA PINTO', 24, '4204558', 1),
+ (4488, 'CRICIUMA', 24, '4204608', 1),
+ (4489, 'CUNHA PORA', 24, '4204707', 1),
+ (4490, 'CUNHATAI', 24, '4204756', 1),
+ (4491, 'CURITIBANOS', 24, '4204806', 1),
+ (4492, 'DESCANSO', 24, '4204905', 1),
+ (4493, 'DIONISIO CERQUEIRA', 24, '4205001', 1),
+ (4494, 'DONA EMMA', 24, '4205100', 1),
+ (4495, 'DOUTOR PEDRINHO', 24, '4205159', 1),
+ (4496, 'ENTRE RIOS', 24, '4205175', 1),
+ (4497, 'ERMO', 24, '4205191', 1),
+ (4498, 'ERVAL VELHO', 24, '4205209', 1),
+ (4499, 'FAXINAL DOS GUEDES', 24, '4205308', 1),
+ (4500, 'FLOR DO SERTAO', 24, '4205357', 1),
+ (4501, 'FLORIANOPOLIS', 24, '4205407', 1),
+ (4502, 'FORMOSA DO SUL', 24, '4205431', 1),
+ (4503, 'FORQUILHINHA', 24, '4205456', 1),
+ (4504, 'FRAIBURGO', 24, '4205506', 1),
+ (4505, 'FREI ROGERIO', 24, '4205555', 1),
+ (4506, 'GALVAO', 24, '4205605', 1),
+ (4507, 'GAROPABA', 24, '4205704', 1),
+ (4508, 'GARUVA', 24, '4205803', 1),
+ (4509, 'GASPAR', 24, '4205902', 1),
+ (4510, 'GOVERNADOR CELSO RAMOS', 24, '4206009', 1),
+ (4511, 'GRAO PARA', 24, '4206108', 1),
+ (4512, 'GRAVATAL', 24, '4206207', 1),
+ (4513, 'GUABIRUBA', 24, '4206306', 1),
+ (4514, 'GUARACIABA', 24, '4206405', 1),
+ (4515, 'GUARAMIRIM', 24, '4206504', 1),
+ (4516, 'GUARUJA DO SUL', 24, '4206603', 1),
+ (4517, 'GUATAMBU', 24, '4206652', 1),
+ (4518, 'HERVAL DOESTE', 24, '4206702', 1),
+ (4519, 'IBIAM', 24, '4206751', 1),
+ (4520, 'IBICARE', 24, '4206801', 1),
+ (4521, 'IBIRAMA', 24, '4206900', 1),
+ (4522, 'ICARA', 24, '4207007', 1),
+ (4523, 'ILHOTA', 24, '4207106', 1),
+ (4524, 'IMARUI', 24, '4207205', 1),
+ (4525, 'IMBITUBA', 24, '4207304', 1),
+ (4526, 'IMBUIA', 24, '4207403', 1),
+ (4527, 'INDAIAL', 24, '4207502', 1),
+ (4528, 'IOMERE', 24, '4207577', 1),
+ (4529, 'IPIRA', 24, '4207601', 1),
+ (4530, 'IPORA DO OESTE', 24, '4207650', 1),
+ (4531, 'IPUACU', 24, '4207684', 1),
+ (4532, 'IPUMIRIM', 24, '4207700', 1),
+ (4533, 'IRACEMINHA', 24, '4207759', 1),
+ (4534, 'IRANI', 24, '4207809', 1),
+ (4535, 'IRATI', 24, '4207858', 1),
+ (4536, 'IRINEOPOLIS', 24, '4207908', 1),
+ (4537, 'ITA', 24, '4208005', 1),
+ (4538, 'ITAIOPOLIS', 24, '4208104', 1),
+ (4539, 'ITAJAI', 24, '4208203', 1),
+ (4540, 'ITAPEMA', 24, '4208302', 1),
+ (4541, 'ITAPIRANGA', 24, '4208401', 1),
+ (4542, 'ITAPOA', 24, '4208450', 1),
+ (4543, 'ITUPORANGA', 24, '4208500', 1),
+ (4544, 'JABORA', 24, '4208609', 1),
+ (4545, 'JACINTO MACHADO', 24, '4208708', 1),
+ (4546, 'JAGUARUNA', 24, '4208807', 1),
+ (4547, 'JARAGUA DO SUL', 24, '4208906', 1),
+ (4548, 'JARDINOPOLIS', 24, '4208955', 1),
+ (4549, 'JOACABA', 24, '4209003', 1),
+ (4550, 'JOINVILLE', 24, '4209102', 1),
+ (4551, 'JOSE BOITEUX', 24, '4209151', 1),
+ (4552, 'JUPIA', 24, '4209177', 1),
+ (4553, 'LACERDOPOLIS', 24, '4209201', 1),
+ (4554, 'LAGES', 24, '4209300', 1),
+ (4555, 'LAGUNA', 24, '4209409', 1),
+ (4556, 'LAJEADO GRANDE', 24, '4209458', 1),
+ (4557, 'LAURENTINO', 24, '4209508', 1),
+ (4558, 'LAURO MULLER', 24, '4209607', 1),
+ (4559, 'LEBON REGIS', 24, '4209706', 1),
+ (4560, 'LEOBERTO LEAL', 24, '4209805', 1),
+ (4561, 'LINDOIA DO SUL', 24, '4209854', 1),
+ (4562, 'LONTRAS', 24, '4209904', 1),
+ (4563, 'LUIZ ALVES', 24, '4210001', 1),
+ (4564, 'LUZERNA', 24, '4210035', 1),
+ (4565, 'MACIEIRA', 24, '4210050', 1),
+ (4566, 'MAFRA', 24, '4210100', 1),
+ (4567, 'MAJOR GERCINO', 24, '4210209', 1),
+ (4568, 'MAJOR VIEIRA', 24, '4210308', 1),
+ (4569, 'MARACAJA', 24, '4210407', 1),
+ (4570, 'MARAVILHA', 24, '4210506', 1),
+ (4571, 'MAREMA', 24, '4210555', 1),
+ (4572, 'MASSARANDUBA', 24, '4210605', 1),
+ (4573, 'MATOS COSTA', 24, '4210704', 1),
+ (4574, 'MELEIRO', 24, '4210803', 1),
+ (4575, 'MIRIM DOCE', 24, '4210852', 1),
+ (4576, 'MODELO', 24, '4210902', 1),
+ (4577, 'MONDAI', 24, '4211009', 1),
+ (4578, 'MONTE CARLO', 24, '4211058', 1),
+ (4579, 'MONTE CASTELO', 24, '4211108', 1),
+ (4580, 'MORRO DA FUMACA', 24, '4211207', 1),
+ (4581, 'MORRO GRANDE', 24, '4211256', 1),
+ (4582, 'NAVEGANTES', 24, '4211306', 1),
+ (4583, 'NOVA ERECHIM', 24, '4211405', 1),
+ (4584, 'NOVA ITABERABA', 24, '4211454', 1),
+ (4585, 'NOVA TRENTO', 24, '4211504', 1),
+ (4586, 'NOVA VENEZA', 24, '4211603', 1),
+ (4587, 'NOVO HORIZONTE', 24, '4211652', 1),
+ (4588, 'ORLEANS', 24, '4211702', 1),
+ (4589, 'OTACILIO COSTA', 24, '4211751', 1),
+ (4590, 'OURO', 24, '4211801', 1),
+ (4591, 'OURO VERDE', 24, '4211850', 1),
+ (4592, 'PAIAL', 24, '4211876', 1),
+ (4593, 'PAINEL', 24, '4211892', 1),
+ (4594, 'PALHOCA', 24, '4211900', 1),
+ (4595, 'PALMA SOLA', 24, '4212007', 1),
+ (4596, 'PALMEIRA', 24, '4212056', 1),
+ (4597, 'PALMITOS', 24, '4212106', 1),
+ (4598, 'PAPANDUVA', 24, '4212205', 1),
+ (4599, 'PARAISO', 24, '4212239', 1),
+ (4600, 'PASSO DE TORRES', 24, '4212254', 1),
+ (4601, 'PASSOS MAIA', 24, '4212270', 1),
+ (4602, 'PAULO LOPES', 24, '4212304', 1),
+ (4603, 'PEDRAS GRANDES', 24, '4212403', 1),
+ (4604, 'PENHA', 24, '4212502', 1),
+ (4605, 'PERITIBA', 24, '4212601', 1),
+ (4606, 'PETROLANDIA', 24, '4212700', 1),
+ (4607, 'BALNEARIO PICARRAS', 24, '4212809', 1),
+ (4608, 'PINHALZINHO', 24, '4212908', 1),
+ (4609, 'PINHEIRO PRETO', 24, '4213005', 1),
+ (4610, 'PIRATUBA', 24, '4213104', 1),
+ (4611, 'PLANALTO ALEGRE', 24, '4213153', 1),
+ (4612, 'POMERODE', 24, '4213203', 1),
+ (4613, 'PONTE ALTA', 24, '4213302', 1),
+ (4614, 'PONTE ALTA DO NORTE', 24, '4213351', 1),
+ (4615, 'PONTE SERRADA', 24, '4213401', 1),
+ (4616, 'PORTO BELO', 24, '4213500', 1),
+ (4617, 'PORTO UNIAO', 24, '4213609', 1),
+ (4618, 'POUSO REDONDO', 24, '4213708', 1),
+ (4619, 'PRAIA GRANDE', 24, '4213807', 1),
+ (4620, 'PRESIDENTE CASTELLO BRANCO', 24, '4213906', 1),
+ (4621, 'PRESIDENTE GETULIO', 24, '4214003', 1),
+ (4622, 'PRESIDENTE NEREU', 24, '4214102', 1),
+ (4623, 'PRINCESA', 24, '4214151', 1),
+ (4624, 'QUILOMBO', 24, '4214201', 1),
+ (4625, 'RANCHO QUEIMADO', 24, '4214300', 1),
+ (4626, 'RIO DAS ANTAS', 24, '4214409', 1),
+ (4627, 'RIO DO CAMPO', 24, '4214508', 1),
+ (4628, 'RIO DO OESTE', 24, '4214607', 1),
+ (4629, 'RIO DOS CEDROS', 24, '4214706', 1),
+ (4630, 'RIO DO SUL', 24, '4214805', 1),
+ (4631, 'RIO FORTUNA', 24, '4214904', 1),
+ (4632, 'RIO NEGRINHO', 24, '4215000', 1),
+ (4633, 'RIO RUFINO', 24, '4215059', 1),
+ (4634, 'RIQUEZA', 24, '4215075', 1),
+ (4635, 'RODEIO', 24, '4215109', 1),
+ (4636, 'ROMELANDIA', 24, '4215208', 1),
+ (4637, 'SALETE', 24, '4215307', 1),
+ (4638, 'SALTINHO', 24, '4215356', 1),
+ (4639, 'SALTO VELOSO', 24, '4215406', 1),
+ (4640, 'SANGAO', 24, '4215455', 1),
+ (4641, 'SANTA CECILIA', 24, '4215505', 1),
+ (4642, 'SANTA HELENA', 24, '4215554', 1),
+ (4643, 'SANTA ROSA DE LIMA', 24, '4215604', 1),
+ (4644, 'SANTA ROSA DO SUL', 24, '4215653', 1),
+ (4645, 'SANTA TEREZINHA', 24, '4215679', 1),
+ (4646, 'SANTA TEREZINHA DO PROGRESSO', 24, '4215687', 1),
+ (4647, 'SANTIAGO DO SUL', 24, '4215695', 1),
+ (4648, 'SANTO AMARO DA IMPERATRIZ', 24, '4215703', 1),
+ (4649, 'SAO BERNARDINO', 24, '4215752', 1),
+ (4650, 'SAO BENTO DO SUL', 24, '4215802', 1),
+ (4651, 'SAO BONIFACIO', 24, '4215901', 1),
+ (4652, 'SAO CARLOS', 24, '4216008', 1),
+ (4653, 'SAO CRISTOVAO DO SUL', 24, '4216057', 1),
+ (4654, 'SAO DOMINGOS', 24, '4216107', 1),
+ (4655, 'SAO FRANCISCO DO SUL', 24, '4216206', 1),
+ (4656, 'SAO JOAO DO OESTE', 24, '4216255', 1),
+ (4657, 'SAO JOAO BATISTA', 24, '4216305', 1),
+ (4658, 'SAO JOAO DO ITAPERIU', 24, '4216354', 1),
+ (4659, 'SAO JOAO DO SUL', 24, '4216404', 1),
+ (4660, 'SAO JOAQUIM', 24, '4216503', 1),
+ (4661, 'SAO JOSE', 24, '4216602', 1),
+ (4662, 'SAO JOSE DO CEDRO', 24, '4216701', 1),
+ (4663, 'SAO JOSE DO CERRITO', 24, '4216800', 1),
+ (4664, 'SAO LOURENCO DO OESTE', 24, '4216909', 1),
+ (4665, 'SAO LUDGERO', 24, '4217006', 1),
+ (4666, 'SAO MARTINHO', 24, '4217105', 1),
+ (4667, 'SAO MIGUEL DA BOA VISTA', 24, '4217154', 1),
+ (4668, 'SAO MIGUEL DO OESTE', 24, '4217204', 1),
+ (4669, 'SAO PEDRO DE ALCANTARA', 24, '4217253', 1),
+ (4670, 'SAUDADES', 24, '4217303', 1),
+ (4671, 'SCHROEDER', 24, '4217402', 1),
+ (4672, 'SEARA', 24, '4217501', 1),
+ (4673, 'SERRA ALTA', 24, '4217550', 1),
+ (4674, 'SIDEROPOLIS', 24, '4217600', 1),
+ (4675, 'SOMBRIO', 24, '4217709', 1),
+ (4676, 'SUL BRASIL', 24, '4217758', 1),
+ (4677, 'TAIO', 24, '4217808', 1),
+ (4678, 'TANGARA', 24, '4217907', 1),
+ (4679, 'TIGRINHOS', 24, '4217956', 1),
+ (4680, 'TIJUCAS', 24, '4218004', 1),
+ (4681, 'TIMBE DO SUL', 24, '4218103', 1),
+ (4682, 'TIMBO', 24, '4218202', 1),
+ (4683, 'TIMBO GRANDE', 24, '4218251', 1),
+ (4684, 'TRES BARRAS', 24, '4218301', 1),
+ (4685, 'TREVISO', 24, '4218350', 1),
+ (4686, 'TREZE DE MAIO', 24, '4218400', 1),
+ (4687, 'TREZE TILIAS', 24, '4218509', 1),
+ (4688, 'TROMBUDO CENTRAL', 24, '4218608', 1),
+ (4689, 'TUBARAO', 24, '4218707', 1),
+ (4690, 'TUNAPOLIS', 24, '4218756', 1),
+ (4691, 'TURVO', 24, '4218806', 1),
+ (4692, 'UNIAO DO OESTE', 24, '4218855', 1),
+ (4693, 'URUBICI', 24, '4218905', 1),
+ (4694, 'URUPEMA', 24, '4218954', 1),
+ (4695, 'URUSSANGA', 24, '4219002', 1),
+ (4696, 'VARGEAO', 24, '4219101', 1),
+ (4697, 'VARGEM', 24, '4219150', 1),
+ (4698, 'VARGEM BONITA', 24, '4219176', 1),
+ (4699, 'VIDAL RAMOS', 24, '4219200', 1),
+ (4700, 'VIDEIRA', 24, '4219309', 1),
+ (4701, 'VITOR MEIRELES', 24, '4219358', 1),
+ (4702, 'WITMARSUM', 24, '4219408', 1),
+ (4703, 'XANXERE', 24, '4219507', 1),
+ (4704, 'XAVANTINA', 24, '4219606', 1),
+ (4705, 'XAXIM', 24, '4219705', 1),
+ (4706, 'ZORTEA', 24, '4219853', 1),
+ (4707, 'AMPARO DE SAO FRANCISCO', 25, '2800100', 1),
+ (4708, 'AQUIDABA', 25, '2800209', 1),
+ (4709, 'ARACAJU', 25, '2800308', 1),
+ (4710, 'ARAUA', 25, '2800407', 1),
+ (4711, 'AREIA BRANCA', 25, '2800506', 1),
+ (4712, 'BARRA DOS COQUEIROS', 25, '2800605', 1),
+ (4713, 'BOQUIM', 25, '2800670', 1),
+ (4714, 'BREJO GRANDE', 25, '2800704', 1),
+ (4715, 'CAMPO DO BRITO', 25, '2801009', 1),
+ (4716, 'CANHOBA', 25, '2801108', 1),
+ (4717, 'CANINDE DE SAO FRANCISCO', 25, '2801207', 1),
+ (4718, 'CAPELA', 25, '2801306', 1),
+ (4719, 'CARIRA', 25, '2801405', 1),
+ (4720, 'CARMOPOLIS', 25, '2801504', 1),
+ (4721, 'CEDRO DE SAO JOAO', 25, '2801603', 1),
+ (4722, 'CRISTINAPOLIS', 25, '2801702', 1),
+ (4723, 'CUMBE', 25, '2801900', 1),
+ (4724, 'DIVINA PASTORA', 25, '2802007', 1),
+ (4725, 'ESTANCIA', 25, '2802106', 1),
+ (4726, 'FEIRA NOVA', 25, '2802205', 1),
+ (4727, 'FREI PAULO', 25, '2802304', 1),
+ (4728, 'GARARU', 25, '2802403', 1),
+ (4729, 'GENERAL MAYNARD', 25, '2802502', 1),
+ (4730, 'GRACHO CARDOSO', 25, '2802601', 1),
+ (4731, 'ILHA DAS FLORES', 25, '2802700', 1),
+ (4732, 'INDIAROBA', 25, '2802809', 1),
+ (4733, 'ITABAIANA', 25, '2802908', 1),
+ (4734, 'ITABAIANINHA', 25, '2803005', 1),
+ (4735, 'ITABI', 25, '2803104', 1),
+ (4736, 'ITAPORANGA DAJUDA', 25, '2803203', 1),
+ (4737, 'JAPARATUBA', 25, '2803302', 1),
+ (4738, 'JAPOATA', 25, '2803401', 1),
+ (4739, 'LAGARTO', 25, '2803500', 1),
+ (4740, 'LARANJEIRAS', 25, '2803609', 1),
+ (4741, 'MACAMBIRA', 25, '2803708', 1),
+ (4742, 'MALHADA DOS BOIS', 25, '2803807', 1),
+ (4743, 'MALHADOR', 25, '2803906', 1),
+ (4744, 'MARUIM', 25, '2804003', 1),
+ (4745, 'MOITA BONITA', 25, '2804102', 1),
+ (4746, 'MONTE ALEGRE DE SERGIPE', 25, '2804201', 1),
+ (4747, 'MURIBECA', 25, '2804300', 1),
+ (4748, 'NEOPOLIS', 25, '2804409', 1),
+ (4749, 'NOSSA SENHORA APARECIDA', 25, '2804458', 1),
+ (4750, 'NOSSA SENHORA DA GLORIA', 25, '2804508', 1),
+ (4751, 'NOSSA SENHORA DAS DORES', 25, '2804607', 1),
+ (4752, 'NOSSA SENHORA DE LOURDES', 25, '2804706', 1),
+ (4753, 'NOSSA SENHORA DO SOCORRO', 25, '2804805', 1),
+ (4754, 'PACATUBA', 25, '2804904', 1),
+ (4755, 'PEDRA MOLE', 25, '2805000', 1),
+ (4756, 'PEDRINHAS', 25, '2805109', 1),
+ (4757, 'PINHAO', 25, '2805208', 1),
+ (4758, 'PIRAMBU', 25, '2805307', 1),
+ (4759, 'POCO REDONDO', 25, '2805406', 1),
+ (4760, 'POCO VERDE', 25, '2805505', 1),
+ (4761, 'PORTO DA FOLHA', 25, '2805604', 1),
+ (4762, 'PROPRIA', 25, '2805703', 1),
+ (4763, 'RIACHAO DO DANTAS', 25, '2805802', 1),
+ (4764, 'RIACHUELO', 25, '2805901', 1),
+ (4765, 'RIBEIROPOLIS', 25, '2806008', 1),
+ (4766, 'ROSARIO DO CATETE', 25, '2806107', 1),
+ (4767, 'SALGADO', 25, '2806206', 1),
+ (4768, 'SANTA LUZIA DO ITANHY', 25, '2806305', 1),
+ (4769, 'SANTANA DO SAO FRANCISCO', 25, '2806404', 1),
+ (4770, 'SANTA ROSA DE LIMA', 25, '2806503', 1),
+ (4771, 'SANTO AMARO DAS BROTAS', 25, '2806602', 1),
+ (4772, 'SAO CRISTOVAO', 25, '2806701', 1),
+ (4773, 'SAO DOMINGOS', 25, '2806800', 1),
+ (4774, 'SAO FRANCISCO', 25, '2806909', 1),
+ (4775, 'SAO MIGUEL DO ALEIXO', 25, '2807006', 1),
+ (4776, 'SIMAO DIAS', 25, '2807105', 1),
+ (4777, 'SIRIRI', 25, '2807204', 1),
+ (4778, 'TELHA', 25, '2807303', 1),
+ (4779, 'TOBIAS BARRETO', 25, '2807402', 1),
+ (4780, 'TOMAR DO GERU', 25, '2807501', 1),
+ (4781, 'UMBAUBA', 25, '2807600', 1),
+ (4782, 'ADAMANTINA', 26, '3500105', 1),
+ (4783, 'ADOLFO', 26, '3500204', 1),
+ (4784, 'AGUAI', 26, '3500303', 1),
+ (4785, 'AGUAS DA PRATA', 26, '3500402', 1),
+ (4786, 'AGUAS DE LINDOIA', 26, '3500501', 1),
+ (4787, 'AGUAS DE SANTA BARBARA', 26, '3500550', 1),
+ (4788, 'AGUAS DE SAO PEDRO', 26, '3500600', 1),
+ (4789, 'AGUDOS', 26, '3500709', 1),
+ (4790, 'ALAMBARI', 26, '3500758', 1),
+ (4791, 'ALFREDO MARCONDES', 26, '3500808', 1),
+ (4792, 'ALTAIR', 26, '3500907', 1),
+ (4793, 'ALTINOPOLIS', 26, '3501004', 1),
+ (4794, 'ALTO ALEGRE', 26, '3501103', 1),
+ (4795, 'ALUMINIO', 26, '3501152', 1),
+ (4796, 'ALVARES FLORENCE', 26, '3501202', 1),
+ (4797, 'ALVARES MACHADO', 26, '3501301', 1),
+ (4798, 'ALVARO DE CARVALHO', 26, '3501400', 1),
+ (4799, 'ALVINLANDIA', 26, '3501509', 1),
+ (4800, 'AMERICANA', 26, '3501608', 1),
+ (4801, 'AMERICO BRASILIENSE', 26, '3501707', 1),
+ (4802, 'AMERICO DE CAMPOS', 26, '3501806', 1),
+ (4803, 'AMPARO', 26, '3501905', 1),
+ (4804, 'ANALANDIA', 26, '3502002', 1),
+ (4805, 'ANDRADINA', 26, '3502101', 1),
+ (4806, 'ANGATUBA', 26, '3502200', 1),
+ (4807, 'ANHEMBI', 26, '3502309', 1),
+ (4808, 'ANHUMAS', 26, '3502408', 1),
+ (4809, 'APARECIDA', 26, '3502507', 1),
+ (4810, 'APARECIDA DOESTE', 26, '3502606', 1),
+ (4811, 'APIAI', 26, '3502705', 1),
+ (4812, 'ARACARIGUAMA', 26, '3502754', 1),
+ (4813, 'ARACATUBA', 26, '3502804', 1),
+ (4814, 'ARACOIABA DA SERRA', 26, '3502903', 1),
+ (4815, 'ARAMINA', 26, '3503000', 1),
+ (4816, 'ARANDU', 26, '3503109', 1),
+ (4817, 'ARAPEI', 26, '3503158', 1),
+ (4818, 'ARARAQUARA', 26, '3503208', 1),
+ (4819, 'ARARAS', 26, '3503307', 1),
+ (4820, 'ARCO-IRIS', 26, '3503356', 1),
+ (4821, 'AREALVA', 26, '3503406', 1),
+ (4822, 'AREIAS', 26, '3503505', 1),
+ (4823, 'AREIOPOLIS', 26, '3503604', 1),
+ (4824, 'ARIRANHA', 26, '3503703', 1),
+ (4825, 'ARTUR NOGUEIRA', 26, '3503802', 1),
+ (4826, 'ARUJA', 26, '3503901', 1),
+ (4827, 'ASPASIA', 26, '3503950', 1),
+ (4828, 'ASSIS', 26, '3504008', 1),
+ (4829, 'ATIBAIA', 26, '3504107', 1),
+ (4830, 'AURIFLAMA', 26, '3504206', 1),
+ (4831, 'AVAI', 26, '3504305', 1),
+ (4832, 'AVANHANDAVA', 26, '3504404', 1),
+ (4833, 'AVARE', 26, '3504503', 1),
+ (4834, 'BADY BASSITT', 26, '3504602', 1),
+ (4835, 'BALBINOS', 26, '3504701', 1),
+ (4836, 'BALSAMO', 26, '3504800', 1),
+ (4837, 'BANANAL', 26, '3504909', 1),
+ (4838, 'BARAO DE ANTONINA', 26, '3505005', 1),
+ (4839, 'BARBOSA', 26, '3505104', 1),
+ (4840, 'BARIRI', 26, '3505203', 1),
+ (4841, 'BARRA BONITA', 26, '3505302', 1),
+ (4842, 'BARRA DO CHAPEU', 26, '3505351', 1),
+ (4843, 'BARRA DO TURVO', 26, '3505401', 1),
+ (4844, 'BARRETOS', 26, '3505500', 1),
+ (4845, 'BARRINHA', 26, '3505609', 1),
+ (4846, 'BARUERI', 26, '3505708', 1),
+ (4847, 'BASTOS', 26, '3505807', 1),
+ (4848, 'BATATAIS', 26, '3505906', 1),
+ (4849, 'BAURU', 26, '3506003', 1),
+ (4850, 'BEBEDOURO', 26, '3506102', 1),
+ (4851, 'BENTO DE ABREU', 26, '3506201', 1),
+ (4852, 'BERNARDINO DE CAMPOS', 26, '3506300', 1),
+ (4853, 'BERTIOGA', 26, '3506359', 1),
+ (4854, 'BILAC', 26, '3506409', 1),
+ (4855, 'BIRIGUI', 26, '3506508', 1),
+ (4856, 'BIRITIBA-MIRIM', 26, '3506607', 1),
+ (4857, 'BOA ESPERANCA DO SUL', 26, '3506706', 1),
+ (4858, 'BOCAINA', 26, '3506805', 1),
+ (4859, 'BOFETE', 26, '3506904', 1),
+ (4860, 'BOITUVA', 26, '3507001', 1),
+ (4861, 'BOM JESUS DOS PERDOES', 26, '3507100', 1),
+ (4862, 'BOM SUCESSO DE ITARARE', 26, '3507159', 1),
+ (4863, 'BORA', 26, '3507209', 1),
+ (4864, 'BORACEIA', 26, '3507308', 1),
+ (4865, 'BORBOREMA', 26, '3507407', 1),
+ (4866, 'BOREBI', 26, '3507456', 1),
+ (4867, 'BOTUCATU', 26, '3507506', 1),
+ (4868, 'BRAGANCA PAULISTA', 26, '3507605', 1),
+ (4869, 'BRAUNA', 26, '3507704', 1),
+ (4870, 'BREJO ALEGRE', 26, '3507753', 1),
+ (4871, 'BRODOWSKI', 26, '3507803', 1),
+ (4872, 'BROTAS', 26, '3507902', 1),
+ (4873, 'BURI', 26, '3508009', 1),
+ (4874, 'BURITAMA', 26, '3508108', 1),
+ (4875, 'BURITIZAL', 26, '3508207', 1),
+ (4876, 'CABRALIA PAULISTA', 26, '3508306', 1),
+ (4877, 'CABREUVA', 26, '3508405', 1),
+ (4878, 'CACAPAVA', 26, '3508504', 1),
+ (4879, 'CACHOEIRA PAULISTA', 26, '3508603', 1),
+ (4880, 'CACONDE', 26, '3508702', 1),
+ (4881, 'CAFELANDIA', 26, '3508801', 1),
+ (4882, 'CAIABU', 26, '3508900', 1),
+ (4883, 'CAIEIRAS', 26, '3509007', 1),
+ (4884, 'CAIUA', 26, '3509106', 1),
+ (4885, 'CAJAMAR', 26, '3509205', 1),
+ (4886, 'CAJATI', 26, '3509254', 1),
+ (4887, 'CAJOBI', 26, '3509304', 1),
+ (4888, 'CAJURU', 26, '3509403', 1),
+ (4889, 'CAMPINA DO MONTE ALEGRE', 26, '3509452', 1),
+ (4890, 'CAMPINAS', 26, '3509502', 1),
+ (4891, 'CAMPO LIMPO PAULISTA', 26, '3509601', 1),
+ (4892, 'CAMPOS DO JORDAO', 26, '3509700', 1),
+ (4893, 'CAMPOS NOVOS PAULISTA', 26, '3509809', 1),
+ (4894, 'CANANEIA', 26, '3509908', 1),
+ (4895, 'CANAS', 26, '3509957', 1),
+ (4896, 'CANDIDO MOTA', 26, '3510005', 1),
+ (4897, 'CANDIDO RODRIGUES', 26, '3510104', 1),
+ (4898, 'CANITAR', 26, '3510153', 1),
+ (4899, 'CAPAO BONITO', 26, '3510203', 1),
+ (4900, 'CAPELA DO ALTO', 26, '3510302', 1),
+ (4901, 'CAPIVARI', 26, '3510401', 1),
+ (4902, 'CARAGUATATUBA', 26, '3510500', 1),
+ (4903, 'CARAPICUIBA', 26, '3510609', 1),
+ (4904, 'CARDOSO', 26, '3510708', 1),
+ (4905, 'CASA BRANCA', 26, '3510807', 1),
+ (4906, 'CASSIA DOS COQUEIROS', 26, '3510906', 1),
+ (4907, 'CASTILHO', 26, '3511003', 1),
+ (4908, 'CATANDUVA', 26, '3511102', 1),
+ (4909, 'CATIGUA', 26, '3511201', 1),
+ (4910, 'CEDRAL', 26, '3511300', 1),
+ (4911, 'CERQUEIRA CESAR', 26, '3511409', 1),
+ (4912, 'CERQUILHO', 26, '3511508', 1),
+ (4913, 'CESARIO LANGE', 26, '3511607', 1),
+ (4914, 'CHARQUEADA', 26, '3511706', 1),
+ (4915, 'CLEMENTINA', 26, '3511904', 1),
+ (4916, 'COLINA', 26, '3512001', 1),
+ (4917, 'COLOMBIA', 26, '3512100', 1),
+ (4918, 'CONCHAL', 26, '3512209', 1),
+ (4919, 'CONCHAS', 26, '3512308', 1),
+ (4920, 'CORDEIROPOLIS', 26, '3512407', 1),
+ (4921, 'COROADOS', 26, '3512506', 1),
+ (4922, 'CORONEL MACEDO', 26, '3512605', 1),
+ (4923, 'CORUMBATAI', 26, '3512704', 1),
+ (4924, 'COSMOPOLIS', 26, '3512803', 1),
+ (4925, 'COSMORAMA', 26, '3512902', 1),
+ (4926, 'COTIA', 26, '3513009', 1),
+ (4927, 'CRAVINHOS', 26, '3513108', 1),
+ (4928, 'CRISTAIS PAULISTA', 26, '3513207', 1),
+ (4929, 'CRUZALIA', 26, '3513306', 1),
+ (4930, 'CRUZEIRO', 26, '3513405', 1),
+ (4931, 'CUBATAO', 26, '3513504', 1),
+ (4932, 'CUNHA', 26, '3513603', 1),
+ (4933, 'DESCALVADO', 26, '3513702', 1),
+ (4934, 'DIADEMA', 26, '3513801', 1),
+ (4935, 'DIRCE REIS', 26, '3513850', 1),
+ (4936, 'DIVINOLANDIA', 26, '3513900', 1),
+ (4937, 'DOBRADA', 26, '3514007', 1),
+ (4938, 'DOIS CORREGOS', 26, '3514106', 1),
+ (4939, 'DOLCINOPOLIS', 26, '3514205', 1),
+ (4940, 'DOURADO', 26, '3514304', 1),
+ (4941, 'DRACENA', 26, '3514403', 1),
+ (4942, 'DUARTINA', 26, '3514502', 1),
+ (4943, 'DUMONT', 26, '3514601', 1),
+ (4944, 'ECHAPORA', 26, '3514700', 1),
+ (4945, 'ELDORADO', 26, '3514809', 1),
+ (4946, 'ELIAS FAUSTO', 26, '3514908', 1),
+ (4947, 'ELISIARIO', 26, '3514924', 1),
+ (4948, 'EMBAUBA', 26, '3514957', 1),
+ (4949, 'EMBU', 26, '3515004', 1),
+ (4950, 'EMBU-GUACU', 26, '3515103', 1),
+ (4951, 'EMILIANOPOLIS', 26, '3515129', 1),
+ (4952, 'ENGENHEIRO COELHO', 26, '3515152', 1),
+ (4953, 'ESPIRITO SANTO DO PINHAL', 26, '3515186', 1),
+ (4954, 'ESPIRITO SANTO DO TURVO', 26, '3515194', 1),
+ (4955, 'ESTRELA DOESTE', 26, '3515202', 1),
+ (4956, 'ESTRELA DO NORTE', 26, '3515301', 1),
+ (4957, 'EUCLIDES DA CUNHA PAULISTA', 26, '3515350', 1),
+ (4958, 'FARTURA', 26, '3515400', 1),
+ (4959, 'FERNANDOPOLIS', 26, '3515509', 1),
+ (4960, 'FERNANDO PRESTES', 26, '3515608', 1),
+ (4961, 'FERNAO', 26, '3515657', 1),
+ (4962, 'FERRAZ DE VASCONCELOS', 26, '3515707', 1),
+ (4963, 'FLORA RICA', 26, '3515806', 1),
+ (4964, 'FLOREAL', 26, '3515905', 1),
+ (4965, 'FLORIDA PAULISTA', 26, '3516002', 1),
+ (4966, 'FLORINIA', 26, '3516101', 1),
+ (4967, 'FRANCA', 26, '3516200', 1),
+ (4968, 'FRANCISCO MORATO', 26, '3516309', 1),
+ (4969, 'FRANCO DA ROCHA', 26, '3516408', 1),
+ (4970, 'GABRIEL MONTEIRO', 26, '3516507', 1),
+ (4971, 'GALIA', 26, '3516606', 1),
+ (4972, 'GARCA', 26, '3516705', 1),
+ (4973, 'GASTAO VIDIGAL', 26, '3516804', 1),
+ (4974, 'GAVIAO PEIXOTO', 26, '3516853', 1),
+ (4975, 'GENERAL SALGADO', 26, '3516903', 1),
+ (4976, 'GETULINA', 26, '3517000', 1),
+ (4977, 'GLICERIO', 26, '3517109', 1),
+ (4978, 'GUAICARA', 26, '3517208', 1),
+ (4979, 'GUAIMBE', 26, '3517307', 1),
+ (4980, 'GUAIRA', 26, '3517406', 1),
+ (4981, 'GUAPIACU', 26, '3517505', 1),
+ (4982, 'GUAPIARA', 26, '3517604', 1),
+ (4983, 'GUARA', 26, '3517703', 1),
+ (4984, 'GUARACAI', 26, '3517802', 1),
+ (4985, 'GUARACI', 26, '3517901', 1),
+ (4986, 'GUARANI DOESTE', 26, '3518008', 1),
+ (4987, 'GUARANTA', 26, '3518107', 1),
+ (4988, 'GUARARAPES', 26, '3518206', 1),
+ (4989, 'GUARAREMA', 26, '3518305', 1),
+ (4990, 'GUARATINGUETA', 26, '3518404', 1),
+ (4991, 'GUAREI', 26, '3518503', 1),
+ (4992, 'GUARIBA', 26, '3518602', 1),
+ (4993, 'GUARUJA', 26, '3518701', 1),
+ (4994, 'GUARULHOS', 26, '3518800', 1),
+ (4995, 'GUATAPARA', 26, '3518859', 1),
+ (4996, 'GUZOLANDIA', 26, '3518909', 1),
+ (4997, 'HERCULANDIA', 26, '3519006', 1),
+ (4998, 'HOLAMBRA', 26, '3519055', 1),
+ (4999, 'HORTOLANDIA', 26, '3519071', 1),
+ (5000, 'IACANGA', 26, '3519105', 1),
+ (5001, 'IACRI', 26, '3519204', 1),
+ (5002, 'IARAS', 26, '3519253', 1),
+ (5003, 'IBATE', 26, '3519303', 1),
+ (5004, 'IBIRA', 26, '3519402', 1),
+ (5005, 'IBIRAREMA', 26, '3519501', 1),
+ (5006, 'IBITINGA', 26, '3519600', 1),
+ (5007, 'IBIUNA', 26, '3519709', 1),
+ (5008, 'ICEM', 26, '3519808', 1),
+ (5009, 'IEPE', 26, '3519907', 1),
+ (5010, 'IGARACU DO TIETE', 26, '3520004', 1),
+ (5011, 'IGARAPAVA', 26, '3520103', 1),
+ (5012, 'IGARATA', 26, '3520202', 1),
+ (5013, 'IGUAPE', 26, '3520301', 1),
+ (5014, 'ILHABELA', 26, '3520400', 1),
+ (5015, 'ILHA COMPRIDA', 26, '3520426', 1),
+ (5016, 'ILHA SOLTEIRA', 26, '3520442', 1),
+ (5017, 'INDAIATUBA', 26, '3520509', 1),
+ (5018, 'INDIANA', 26, '3520608', 1),
+ (5019, 'INDIAPORA', 26, '3520707', 1),
+ (5020, 'INUBIA PAULISTA', 26, '3520806', 1),
+ (5021, 'IPAUSSU', 26, '3520905', 1),
+ (5022, 'IPERO', 26, '3521002', 1),
+ (5023, 'IPEUNA', 26, '3521101', 1),
+ (5024, 'IPIGUA', 26, '3521150', 1),
+ (5025, 'IPORANGA', 26, '3521200', 1),
+ (5026, 'IPUA', 26, '3521309', 1),
+ (5027, 'IRACEMAPOLIS', 26, '3521408', 1),
+ (5028, 'IRAPUA', 26, '3521507', 1),
+ (5029, 'IRAPURU', 26, '3521606', 1),
+ (5030, 'ITABERA', 26, '3521705', 1),
+ (5031, 'ITAI', 26, '3521804', 1),
+ (5032, 'ITAJOBI', 26, '3521903', 1),
+ (5033, 'ITAJU', 26, '3522000', 1),
+ (5034, 'ITANHAEM', 26, '3522109', 1),
+ (5035, 'ITAOCA', 26, '3522158', 1),
+ (5036, 'ITAPECERICA DA SERRA', 26, '3522208', 1),
+ (5037, 'ITAPETININGA', 26, '3522307', 1),
+ (5038, 'ITAPEVA', 26, '3522406', 1),
+ (5039, 'ITAPEVI', 26, '3522505', 1),
+ (5040, 'ITAPIRA', 26, '3522604', 1),
+ (5041, 'ITAPIRAPUA PAULISTA', 26, '3522653', 1),
+ (5042, 'ITAPOLIS', 26, '3522703', 1),
+ (5043, 'ITAPORANGA', 26, '3522802', 1),
+ (5044, 'ITAPUI', 26, '3522901', 1),
+ (5045, 'ITAPURA', 26, '3523008', 1),
+ (5046, 'ITAQUAQUECETUBA', 26, '3523107', 1),
+ (5047, 'ITARARE', 26, '3523206', 1),
+ (5048, 'ITARIRI', 26, '3523305', 1),
+ (5049, 'ITATIBA', 26, '3523404', 1),
+ (5050, 'ITATINGA', 26, '3523503', 1),
+ (5051, 'ITIRAPINA', 26, '3523602', 1),
+ (5052, 'ITIRAPUA', 26, '3523701', 1),
+ (5053, 'ITOBI', 26, '3523800', 1),
+ (5054, 'ITU', 26, '3523909', 1),
+ (5055, 'ITUPEVA', 26, '3524006', 1),
+ (5056, 'ITUVERAVA', 26, '3524105', 1),
+ (5057, 'JABORANDI', 26, '3524204', 1),
+ (5058, 'JABOTICABAL', 26, '3524303', 1),
+ (5059, 'JACAREI', 26, '3524402', 1),
+ (5060, 'JACI', 26, '3524501', 1),
+ (5061, 'JACUPIRANGA', 26, '3524600', 1),
+ (5062, 'JAGUARIUNA', 26, '3524709', 1),
+ (5063, 'JALES', 26, '3524808', 1),
+ (5064, 'JAMBEIRO', 26, '3524907', 1),
+ (5065, 'JANDIRA', 26, '3525003', 1),
+ (5066, 'JARDINOPOLIS', 26, '3525102', 1),
+ (5067, 'JARINU', 26, '3525201', 1),
+ (5068, 'JAU', 26, '3525300', 1),
+ (5069, 'JERIQUARA', 26, '3525409', 1),
+ (5070, 'JOANOPOLIS', 26, '3525508', 1),
+ (5071, 'JOAO RAMALHO', 26, '3525607', 1),
+ (5072, 'JOSE BONIFACIO', 26, '3525706', 1),
+ (5073, 'JULIO MESQUITA', 26, '3525805', 1),
+ (5074, 'JUMIRIM', 26, '3525854', 1),
+ (5075, 'JUNDIAI', 26, '3525904', 1),
+ (5076, 'JUNQUEIROPOLIS', 26, '3526001', 1),
+ (5077, 'JUQUIA', 26, '3526100', 1),
+ (5078, 'JUQUITIBA', 26, '3526209', 1),
+ (5079, 'LAGOINHA', 26, '3526308', 1),
+ (5080, 'LARANJAL PAULISTA', 26, '3526407', 1),
+ (5081, 'LAVINIA', 26, '3526506', 1),
+ (5082, 'LAVRINHAS', 26, '3526605', 1),
+ (5083, 'LEME', 26, '3526704', 1),
+ (5084, 'LENCOIS PAULISTA', 26, '3526803', 1),
+ (5085, 'LIMEIRA', 26, '3526902', 1),
+ (5086, 'LINDOIA', 26, '3527009', 1),
+ (5087, 'LINS', 26, '3527108', 1),
+ (5088, 'LORENA', 26, '3527207', 1),
+ (5089, 'LOURDES', 26, '3527256', 1),
+ (5090, 'LOUVEIRA', 26, '3527306', 1),
+ (5091, 'LUCELIA', 26, '3527405', 1),
+ (5092, 'LUCIANOPOLIS', 26, '3527504', 1),
+ (5093, 'LUIS ANTONIO', 26, '3527603', 1),
+ (5094, 'LUIZIANIA', 26, '3527702', 1),
+ (5095, 'LUPERCIO', 26, '3527801', 1),
+ (5096, 'LUTECIA', 26, '3527900', 1),
+ (5097, 'MACATUBA', 26, '3528007', 1),
+ (5098, 'MACAUBAL', 26, '3528106', 1),
+ (5099, 'MACEDONIA', 26, '3528205', 1),
+ (5100, 'MAGDA', 26, '3528304', 1),
+ (5101, 'MAIRINQUE', 26, '3528403', 1),
+ (5102, 'MAIRIPORA', 26, '3528502', 1),
+ (5103, 'MANDURI', 26, '3528601', 1),
+ (5104, 'MARABA PAULISTA', 26, '3528700', 1),
+ (5105, 'MARACAI', 26, '3528809', 1),
+ (5106, 'MARAPOAMA', 26, '3528858', 1),
+ (5107, 'MARIAPOLIS', 26, '3528908', 1),
+ (5108, 'MARILIA', 26, '3529005', 1),
+ (5109, 'MARINOPOLIS', 26, '3529104', 1),
+ (5110, 'MARTINOPOLIS', 26, '3529203', 1),
+ (5111, 'MATAO', 26, '3529302', 1),
+ (5112, 'MAUA', 26, '3529401', 1),
+ (5113, 'MENDONCA', 26, '3529500', 1),
+ (5114, 'MERIDIANO', 26, '3529609', 1),
+ (5115, 'MESOPOLIS', 26, '3529658', 1),
+ (5116, 'MIGUELOPOLIS', 26, '3529708', 1),
+ (5117, 'MINEIROS DO TIETE', 26, '3529807', 1),
+ (5118, 'MIRACATU', 26, '3529906', 1),
+ (5119, 'MIRA ESTRELA', 26, '3530003', 1),
+ (5120, 'MIRANDOPOLIS', 26, '3530102', 1),
+ (5121, 'MIRANTE DO PARANAPANEMA', 26, '3530201', 1),
+ (5122, 'MIRASSOL', 26, '3530300', 1),
+ (5123, 'MIRASSOLANDIA', 26, '3530409', 1),
+ (5124, 'MOCOCA', 26, '3530508', 1),
+ (5125, 'MOGI DAS CRUZES', 26, '3530607', 1),
+ (5126, 'MOGI GUACU', 26, '3530706', 1),
+ (5127, 'MOJI MIRIM', 26, '3530805', 1),
+ (5128, 'MOMBUCA', 26, '3530904', 1),
+ (5129, 'MONCOES', 26, '3531001', 1),
+ (5130, 'MONGAGUA', 26, '3531100', 1),
+ (5131, 'MONTE ALEGRE DO SUL', 26, '3531209', 1),
+ (5132, 'MONTE ALTO', 26, '3531308', 1),
+ (5133, 'MONTE APRAZIVEL', 26, '3531407', 1),
+ (5134, 'MONTE AZUL PAULISTA', 26, '3531506', 1),
+ (5135, 'MONTE CASTELO', 26, '3531605', 1),
+ (5136, 'MONTEIRO LOBATO', 26, '3531704', 1),
+ (5137, 'MONTE MOR', 26, '3531803', 1),
+ (5138, 'MORRO AGUDO', 26, '3531902', 1),
+ (5139, 'MORUNGABA', 26, '3532009', 1),
+ (5140, 'MOTUCA', 26, '3532058', 1),
+ (5141, 'MURUTINGA DO SUL', 26, '3532108', 1),
+ (5142, 'NANTES', 26, '3532157', 1),
+ (5143, 'NARANDIBA', 26, '3532207', 1),
+ (5144, 'NATIVIDADE DA SERRA', 26, '3532306', 1),
+ (5145, 'NAZARE PAULISTA', 26, '3532405', 1),
+ (5146, 'NEVES PAULISTA', 26, '3532504', 1),
+ (5147, 'NHANDEARA', 26, '3532603', 1),
+ (5148, 'NIPOA', 26, '3532702', 1),
+ (5149, 'NOVA ALIANCA', 26, '3532801', 1),
+ (5150, 'NOVA CAMPINA', 26, '3532827', 1),
+ (5151, 'NOVA CANAA PAULISTA', 26, '3532843', 1),
+ (5152, 'NOVA CASTILHO', 26, '3532868', 1),
+ (5153, 'NOVA EUROPA', 26, '3532900', 1),
+ (5154, 'NOVA GRANADA', 26, '3533007', 1),
+ (5155, 'NOVA GUATAPORANGA', 26, '3533106', 1),
+ (5156, 'NOVA INDEPENDENCIA', 26, '3533205', 1),
+ (5157, 'NOVAIS', 26, '3533254', 1),
+ (5158, 'NOVA LUZITANIA', 26, '3533304', 1),
+ (5159, 'NOVA ODESSA', 26, '3533403', 1),
+ (5160, 'NOVO HORIZONTE', 26, '3533502', 1),
+ (5161, 'NUPORANGA', 26, '3533601', 1),
+ (5162, 'OCAUCU', 26, '3533700', 1),
+ (5163, 'OLEO', 26, '3533809', 1),
+ (5164, 'OLIMPIA', 26, '3533908', 1),
+ (5165, 'ONDA VERDE', 26, '3534005', 1),
+ (5166, 'ORIENTE', 26, '3534104', 1),
+ (5167, 'ORINDIUVA', 26, '3534203', 1),
+ (5168, 'ORLANDIA', 26, '3534302', 1),
+ (5169, 'OSASCO', 26, '3534401', 1),
+ (5170, 'OSCAR BRESSANE', 26, '3534500', 1),
+ (5171, 'OSVALDO CRUZ', 26, '3534609', 1),
+ (5172, 'OURINHOS', 26, '3534708', 1),
+ (5173, 'OUROESTE', 26, '3534757', 1),
+ (5174, 'OURO VERDE', 26, '3534807', 1),
+ (5175, 'PACAEMBU', 26, '3534906', 1),
+ (5176, 'PALESTINA', 26, '3535002', 1),
+ (5177, 'PALMARES PAULISTA', 26, '3535101', 1),
+ (5178, 'PALMEIRA DOESTE', 26, '3535200', 1),
+ (5179, 'PALMITAL', 26, '3535309', 1),
+ (5180, 'PANORAMA', 26, '3535408', 1),
+ (5181, 'PARAGUACU PAULISTA', 26, '3535507', 1),
+ (5182, 'PARAIBUNA', 26, '3535606', 1),
+ (5183, 'PARAISO', 26, '3535705', 1),
+ (5184, 'PARANAPANEMA', 26, '3535804', 1),
+ (5185, 'PARANAPUA', 26, '3535903', 1),
+ (5186, 'PARAPUA', 26, '3536000', 1),
+ (5187, 'PARDINHO', 26, '3536109', 1),
+ (5188, 'PARIQUERA-ACU', 26, '3536208', 1),
+ (5189, 'PARISI', 26, '3536257', 1),
+ (5190, 'PATROCINIO PAULISTA', 26, '3536307', 1),
+ (5191, 'PAULICEIA', 26, '3536406', 1),
+ (5192, 'PAULINIA', 26, '3536505', 1),
+ (5193, 'PAULISTANIA', 26, '3536570', 1),
+ (5194, 'PAULO DE FARIA', 26, '3536604', 1),
+ (5195, 'PEDERNEIRAS', 26, '3536703', 1),
+ (5196, 'PEDRA BELA', 26, '3536802', 1),
+ (5197, 'PEDRANOPOLIS', 26, '3536901', 1),
+ (5198, 'PEDREGULHO', 26, '3537008', 1),
+ (5199, 'PEDREIRA', 26, '3537107', 1),
+ (5200, 'PEDRINHAS PAULISTA', 26, '3537156', 1),
+ (5201, 'PEDRO DE TOLEDO', 26, '3537206', 1),
+ (5202, 'PENAPOLIS', 26, '3537305', 1),
+ (5203, 'PEREIRA BARRETO', 26, '3537404', 1),
+ (5204, 'PEREIRAS', 26, '3537503', 1),
+ (5205, 'PERUIBE', 26, '3537602', 1),
+ (5206, 'PIACATU', 26, '3537701', 1),
+ (5207, 'PIEDADE', 26, '3537800', 1),
+ (5208, 'PILAR DO SUL', 26, '3537909', 1),
+ (5209, 'PINDAMONHANGABA', 26, '3538006', 1),
+ (5210, 'PINDORAMA', 26, '3538105', 1),
+ (5211, 'PINHALZINHO', 26, '3538204', 1),
+ (5212, 'PIQUEROBI', 26, '3538303', 1),
+ (5213, 'PIQUETE', 26, '3538501', 1),
+ (5214, 'PIRACAIA', 26, '3538600', 1),
+ (5215, 'PIRACICABA', 26, '3538709', 1),
+ (5216, 'PIRAJU', 26, '3538808', 1),
+ (5217, 'PIRAJUI', 26, '3538907', 1),
+ (5218, 'PIRANGI', 26, '3539004', 1),
+ (5219, 'PIRAPORA DO BOM JESUS', 26, '3539103', 1),
+ (5220, 'PIRAPOZINHO', 26, '3539202', 1),
+ (5221, 'PIRASSUNUNGA', 26, '3539301', 1),
+ (5222, 'PIRATININGA', 26, '3539400', 1),
+ (5223, 'PITANGUEIRAS', 26, '3539509', 1),
+ (5224, 'PLANALTO', 26, '3539608', 1),
+ (5225, 'PLATINA', 26, '3539707', 1),
+ (5226, 'POA', 26, '3539806', 1),
+ (5227, 'POLONI', 26, '3539905', 1),
+ (5228, 'POMPEIA', 26, '3540002', 1),
+ (5229, 'PONGAI', 26, '3540101', 1),
+ (5230, 'PONTAL', 26, '3540200', 1),
+ (5231, 'PONTALINDA', 26, '3540259', 1),
+ (5232, 'PONTES GESTAL', 26, '3540309', 1),
+ (5233, 'POPULINA', 26, '3540408', 1),
+ (5234, 'PORANGABA', 26, '3540507', 1),
+ (5235, 'PORTO FELIZ', 26, '3540606', 1),
+ (5236, 'PORTO FERREIRA', 26, '3540705', 1),
+ (5237, 'POTIM', 26, '3540754', 1),
+ (5238, 'POTIRENDABA', 26, '3540804', 1),
+ (5239, 'PRACINHA', 26, '3540853', 1),
+ (5240, 'PRADOPOLIS', 26, '3540903', 1),
+ (5241, 'PRAIA GRANDE', 26, '3541000', 1),
+ (5242, 'PRATANIA', 26, '3541059', 1),
+ (5243, 'PRESIDENTE ALVES', 26, '3541109', 1),
+ (5244, 'PRESIDENTE BERNARDES', 26, '3541208', 1),
+ (5245, 'PRESIDENTE EPITACIO', 26, '3541307', 1),
+ (5246, 'PRESIDENTE PRUDENTE', 26, '3541406', 1),
+ (5247, 'PRESIDENTE VENCESLAU', 26, '3541505', 1),
+ (5248, 'PROMISSAO', 26, '3541604', 1),
+ (5249, 'QUADRA', 26, '3541653', 1),
+ (5250, 'QUATA', 26, '3541703', 1),
+ (5251, 'QUEIROZ', 26, '3541802', 1),
+ (5252, 'QUELUZ', 26, '3541901', 1),
+ (5253, 'QUINTANA', 26, '3542008', 1),
+ (5254, 'RAFARD', 26, '3542107', 1),
+ (5255, 'RANCHARIA', 26, '3542206', 1),
+ (5256, 'REDENCAO DA SERRA', 26, '3542305', 1),
+ (5257, 'REGENTE FEIJO', 26, '3542404', 1),
+ (5258, 'REGINOPOLIS', 26, '3542503', 1),
+ (5259, 'REGISTRO', 26, '3542602', 1),
+ (5260, 'RESTINGA', 26, '3542701', 1),
+ (5261, 'RIBEIRA', 26, '3542800', 1),
+ (5262, 'RIBEIRAO BONITO', 26, '3542909', 1),
+ (5263, 'RIBEIRAO BRANCO', 26, '3543006', 1),
+ (5264, 'RIBEIRAO CORRENTE', 26, '3543105', 1),
+ (5265, 'RIBEIRAO DO SUL', 26, '3543204', 1),
+ (5266, 'RIBEIRAO DOS INDIOS', 26, '3543238', 1),
+ (5267, 'RIBEIRAO GRANDE', 26, '3543253', 1),
+ (5268, 'RIBEIRAO PIRES', 26, '3543303', 1),
+ (5269, 'RIBEIRAO PRETO', 26, '3543402', 1),
+ (5270, 'RIVERSUL', 26, '3543501', 1),
+ (5271, 'RIFAINA', 26, '3543600', 1),
+ (5272, 'RINCAO', 26, '3543709', 1),
+ (5273, 'RINOPOLIS', 26, '3543808', 1),
+ (5274, 'RIO CLARO', 26, '3543907', 1),
+ (5275, 'RIO DAS PEDRAS', 26, '3544004', 1),
+ (5276, 'RIO GRANDE DA SERRA', 26, '3544103', 1),
+ (5277, 'RIOLANDIA', 26, '3544202', 1),
+ (5278, 'ROSANA', 26, '3544251', 1),
+ (5279, 'ROSEIRA', 26, '3544301', 1),
+ (5280, 'RUBIACEA', 26, '3544400', 1),
+ (5281, 'RUBINEIA', 26, '3544509', 1),
+ (5282, 'SABINO', 26, '3544608', 1),
+ (5283, 'SAGRES', 26, '3544707', 1),
+ (5284, 'SALES', 26, '3544806', 1),
+ (5285, 'SALES OLIVEIRA', 26, '3544905', 1),
+ (5286, 'SALESOPOLIS', 26, '3545001', 1),
+ (5287, 'SALMOURAO', 26, '3545100', 1),
+ (5288, 'SALTINHO', 26, '3545159', 1),
+ (5289, 'SALTO', 26, '3545209', 1),
+ (5290, 'SALTO DE PIRAPORA', 26, '3545308', 1),
+ (5291, 'SALTO GRANDE', 26, '3545407', 1),
+ (5292, 'SANDOVALINA', 26, '3545506', 1),
+ (5293, 'SANTA ADELIA', 26, '3545605', 1),
+ (5294, 'SANTA ALBERTINA', 26, '3545704', 1),
+ (5295, 'SANTA BARBARA DOESTE', 26, '3545803', 1),
+ (5296, 'SANTA BRANCA', 26, '3546009', 1),
+ (5297, 'SANTA CLARA DOESTE', 26, '3546108', 1),
+ (5298, 'SANTA CRUZ DA CONCEICAO', 26, '3546207', 1),
+ (5299, 'SANTA CRUZ DA ESPERANCA', 26, '3546256', 1),
+ (5300, 'SANTA CRUZ DAS PALMEIRAS', 26, '3546306', 1),
+ (5301, 'SANTA CRUZ DO RIO PARDO', 26, '3546405', 1),
+ (5302, 'SANTA ERNESTINA', 26, '3546504', 1),
+ (5303, 'SANTA FE DO SUL', 26, '3546603', 1),
+ (5304, 'SANTA GERTRUDES', 26, '3546702', 1),
+ (5305, 'SANTA ISABEL', 26, '3546801', 1),
+ (5306, 'SANTA LUCIA', 26, '3546900', 1),
+ (5307, 'SANTA MARIA DA SERRA', 26, '3547007', 1),
+ (5308, 'SANTA MERCEDES', 26, '3547106', 1),
+ (5309, 'SANTANA DA PONTE PENSA', 26, '3547205', 1),
+ (5310, 'SANTANA DE PARNAIBA', 26, '3547304', 1),
+ (5311, 'SANTA RITA DOESTE', 26, '3547403', 1),
+ (5312, 'SANTA RITA DO PASSA QUATRO', 26, '3547502', 1),
+ (5313, 'SANTA ROSA DE VITERBO', 26, '3547601', 1),
+ (5314, 'SANTA SALETE', 26, '3547650', 1),
+ (5315, 'SANTO ANASTACIO', 26, '3547700', 1),
+ (5316, 'SANTO ANDRE', 26, '3547809', 1),
+ (5317, 'SANTO ANTONIO DA ALEGRIA', 26, '3547908', 1),
+ (5318, 'SANTO ANTONIO DE POSSE', 26, '3548005', 1),
+ (5319, 'SANTO ANTONIO DO ARACANGUA', 26, '3548054', 1),
+ (5320, 'SANTO ANTONIO DO JARDIM', 26, '3548104', 1),
+ (5321, 'SANTO ANTONIO DO PINHAL', 26, '3548203', 1),
+ (5322, 'SANTO EXPEDITO', 26, '3548302', 1),
+ (5323, 'SANTOPOLIS DO AGUAPEI', 26, '3548401', 1),
+ (5324, 'SANTOS', 26, '3548500', 1),
+ (5325, 'SAO BENTO DO SAPUCAI', 26, '3548609', 1),
+ (5326, 'SAO BERNARDO DO CAMPO', 26, '3548708', 1),
+ (5327, 'SAO CAETANO DO SUL', 26, '3548807', 1),
+ (5328, 'SAO CARLOS', 26, '3548906', 1),
+ (5329, 'SAO FRANCISCO', 26, '3549003', 1),
+ (5330, 'SAO JOAO DA BOA VISTA', 26, '3549102', 1),
+ (5331, 'SAO JOAO DAS DUAS PONTES', 26, '3549201', 1),
+ (5332, 'SAO JOAO DE IRACEMA', 26, '3549250', 1),
+ (5333, 'SAO JOAO DO PAU DALHO', 26, '3549300', 1),
+ (5334, 'SAO JOAQUIM DA BARRA', 26, '3549409', 1),
+ (5335, 'SAO JOSE DA BELA VISTA', 26, '3549508', 1),
+ (5336, 'SAO JOSE DO BARREIRO', 26, '3549607', 1),
+ (5337, 'SAO JOSE DO RIO PARDO', 26, '3549706', 1),
+ (5338, 'SAO JOSE DO RIO PRETO', 26, '3549805', 1),
+ (5339, 'SAO JOSE DOS CAMPOS', 26, '3549904', 1),
+ (5340, 'SAO LOURENCO DA SERRA', 26, '3549953', 1),
+ (5341, 'SAO LUIS DO PARAITINGA', 26, '3550001', 1),
+ (5342, 'SAO MANUEL', 26, '3550100', 1),
+ (5343, 'SAO MIGUEL ARCANJO', 26, '3550209', 1),
+ (5344, 'SAO PAULO', 26, '3550308', 1),
+ (5345, 'SAO PEDRO', 26, '3550407', 1),
+ (5346, 'SAO PEDRO DO TURVO', 26, '3550506', 1),
+ (5347, 'SAO ROQUE', 26, '3550605', 1),
+ (5348, 'SAO SEBASTIAO', 26, '3550704', 1),
+ (5349, 'SAO SEBASTIAO DA GRAMA', 26, '3550803', 1),
+ (5350, 'SAO SIMAO', 26, '3550902', 1),
+ (5351, 'SAO VICENTE', 26, '3551009', 1),
+ (5352, 'SARAPUI', 26, '3551108', 1),
+ (5353, 'SARUTAIA', 26, '3551207', 1),
+ (5354, 'SEBASTIANOPOLIS DO SUL', 26, '3551306', 1),
+ (5355, 'SERRA AZUL', 26, '3551405', 1),
+ (5356, 'SERRANA', 26, '3551504', 1),
+ (5357, 'SERRA NEGRA', 26, '3551603', 1),
+ (5358, 'SERTAOZINHO', 26, '3551702', 1),
+ (5359, 'SETE BARRAS', 26, '3551801', 1),
+ (5360, 'SEVERINIA', 26, '3551900', 1),
+ (5361, 'SILVEIRAS', 26, '3552007', 1),
+ (5362, 'SOCORRO', 26, '3552106', 1),
+ (5363, 'SOROCABA', 26, '3552205', 1),
+ (5364, 'SUD MENNUCCI', 26, '3552304', 1),
+ (5365, 'SUMARE', 26, '3552403', 1),
+ (5366, 'SUZANO', 26, '3552502', 1),
+ (5367, 'SUZANAPOLIS', 26, '3552551', 1),
+ (5368, 'TABAPUA', 26, '3552601', 1),
+ (5369, 'TABATINGA', 26, '3552700', 1),
+ (5370, 'TABOAO DA SERRA', 26, '3552809', 1),
+ (5371, 'TACIBA', 26, '3552908', 1),
+ (5372, 'TAGUAI', 26, '3553005', 1),
+ (5373, 'TAIACU', 26, '3553104', 1),
+ (5374, 'TAIUVA', 26, '3553203', 1),
+ (5375, 'TAMBAU', 26, '3553302', 1),
+ (5376, 'TANABI', 26, '3553401', 1),
+ (5377, 'TAPIRAI', 26, '3553500', 1),
+ (5378, 'TAPIRATIBA', 26, '3553609', 1),
+ (5379, 'TAQUARAL', 26, '3553658', 1),
+ (5380, 'TAQUARITINGA', 26, '3553708', 1),
+ (5381, 'TAQUARITUBA', 26, '3553807', 1),
+ (5382, 'TAQUARIVAI', 26, '3553856', 1),
+ (5383, 'TARABAI', 26, '3553906', 1),
+ (5384, 'TARUMA', 26, '3553955', 1),
+ (5385, 'TATUI', 26, '3554003', 1),
+ (5386, 'TAUBATE', 26, '3554102', 1),
+ (5387, 'TEJUPA', 26, '3554201', 1),
+ (5388, 'TEODORO SAMPAIO', 26, '3554300', 1),
+ (5389, 'TERRA ROXA', 26, '3554409', 1),
+ (5390, 'TIETE', 26, '3554508', 1),
+ (5391, 'TIMBURI', 26, '3554607', 1),
+ (5392, 'TORRE DE PEDRA', 26, '3554656', 1),
+ (5393, 'TORRINHA', 26, '3554706', 1),
+ (5394, 'TRABIJU', 26, '3554755', 1),
+ (5395, 'TREMEMBE', 26, '3554805', 1),
+ (5396, 'TRES FRONTEIRAS', 26, '3554904', 1),
+ (5397, 'TUIUTI', 26, '3554953', 1),
+ (5398, 'TUPA', 26, '3555000', 1),
+ (5399, 'TUPI PAULISTA', 26, '3555109', 1),
+ (5400, 'TURIUBA', 26, '3555208', 1),
+ (5401, 'TURMALINA', 26, '3555307', 1),
+ (5402, 'UBARANA', 26, '3555356', 1),
+ (5403, 'UBATUBA', 26, '3555406', 1),
+ (5404, 'UBIRAJARA', 26, '3555505', 1),
+ (5405, 'UCHOA', 26, '3555604', 1),
+ (5406, 'UNIAO PAULISTA', 26, '3555703', 1),
+ (5407, 'URANIA', 26, '3555802', 1),
+ (5408, 'URU', 26, '3555901', 1),
+ (5409, 'URUPES', 26, '3556008', 1),
+ (5410, 'VALENTIM GENTIL', 26, '3556107', 1),
+ (5411, 'VALINHOS', 26, '3556206', 1),
+ (5412, 'VALPARAISO', 26, '3556305', 1),
+ (5413, 'VARGEM', 26, '3556354', 1),
+ (5414, 'VARGEM GRANDE DO SUL', 26, '3556404', 1),
+ (5415, 'VARGEM GRANDE PAULISTA', 26, '3556453', 1),
+ (5416, 'VARZEA PAULISTA', 26, '3556503', 1),
+ (5417, 'VERA CRUZ', 26, '3556602', 1),
+ (5418, 'VINHEDO', 26, '3556701', 1),
+ (5419, 'VIRADOURO', 26, '3556800', 1),
+ (5420, 'VISTA ALEGRE DO ALTO', 26, '3556909', 1),
+ (5421, 'VITORIA BRASIL', 26, '3556958', 1),
+ (5422, 'VOTORANTIM', 26, '3557006', 1),
+ (5423, 'VOTUPORANGA', 26, '3557105', 1),
+ (5424, 'ZACARIAS', 26, '3557154', 1),
+ (5425, 'CHAVANTES', 26, '3557204', 1),
+ (5426, 'ESTIVA GERBI', 26, '3557303', 1),
+ (5427, 'ABREULANDIA', 27, '1700251', 1),
+ (5428, 'AGUIARNOPOLIS', 27, '1700301', 1),
+ (5429, 'ALIANCA DO TOCANTINS', 27, '1700350', 1),
+ (5430, 'ALMAS', 27, '1700400', 1),
+ (5431, 'ALVORADA', 27, '1700707', 1),
+ (5432, 'ANANAS', 27, '1701002', 1),
+ (5433, 'ANGICO', 27, '1701051', 1),
+ (5434, 'APARECIDA DO RIO NEGRO', 27, '1701101', 1),
+ (5435, 'ARAGOMINAS', 27, '1701309', 1),
+ (5436, 'ARAGUACEMA', 27, '1701903', 1),
+ (5437, 'ARAGUACU', 27, '1702000', 1),
+ (5438, 'ARAGUAINA', 27, '1702109', 1),
+ (5439, 'ARAGUANA', 27, '1702158', 1),
+ (5440, 'ARAGUATINS', 27, '1702208', 1),
+ (5441, 'ARAPOEMA', 27, '1702307', 1),
+ (5442, 'ARRAIAS', 27, '1702406', 1),
+ (5443, 'AUGUSTINOPOLIS', 27, '1702554', 1),
+ (5444, 'AURORA DO TOCANTINS', 27, '1702703', 1),
+ (5445, 'AXIXA DO TOCANTINS', 27, '1702901', 1),
+ (5446, 'BABACULANDIA', 27, '1703008', 1),
+ (5447, 'BANDEIRANTES DO TOCANTINS', 27, '1703057', 1),
+ (5448, 'BARRA DO OURO', 27, '1703073', 1),
+ (5449, 'BARROLANDIA', 27, '1703107', 1),
+ (5450, 'BERNARDO SAYAO', 27, '1703206', 1),
+ (5451, 'BOM JESUS DO TOCANTINS', 27, '1703305', 1),
+ (5452, 'BRASILANDIA DO TOCANTINS', 27, '1703602', 1),
+ (5453, 'BREJINHO DE NAZARE', 27, '1703701', 1),
+ (5454, 'BURITI DO TOCANTINS', 27, '1703800', 1),
+ (5455, 'CACHOEIRINHA', 27, '1703826', 1),
+ (5456, 'CAMPOS LINDOS', 27, '1703842', 1),
+ (5457, 'CARIRI DO TOCANTINS', 27, '1703867', 1),
+ (5458, 'CARMOLANDIA', 27, '1703883', 1),
+ (5459, 'CARRASCO BONITO', 27, '1703891', 1),
+ (5460, 'CASEARA', 27, '1703909', 1),
+ (5461, 'CENTENARIO', 27, '1704105', 1),
+ (5462, 'CHAPADA DE AREIA', 27, '1704600', 1),
+ (5463, 'CHAPADA DA NATIVIDADE', 27, '1705102', 1),
+ (5464, 'COLINAS DO TOCANTINS', 27, '1705508', 1),
+ (5465, 'COMBINADO', 27, '1705557', 1),
+ (5466, 'CONCEICAO DO TOCANTINS', 27, '1705607', 1),
+ (5467, 'COUTO MAGALHAES', 27, '1706001', 1),
+ (5468, 'CRISTALANDIA', 27, '1706100', 1),
+ (5469, 'CRIXAS DO TOCANTINS', 27, '1706258', 1),
+ (5470, 'DARCINOPOLIS', 27, '1706506', 1),
+ (5471, 'DIANOPOLIS', 27, '1707009', 1),
+ (5472, 'DIVINOPOLIS DO TOCANTINS', 27, '1707108', 1),
+ (5473, 'DOIS IRMAOS DO TOCANTINS', 27, '1707207', 1),
+ (5474, 'DUERE', 27, '1707306', 1),
+ (5475, 'ESPERANTINA', 27, '1707405', 1),
+ (5476, 'FATIMA', 27, '1707553', 1),
+ (5477, 'FIGUEIROPOLIS', 27, '1707652', 1),
+ (5478, 'FILADELFIA', 27, '1707702', 1),
+ (5479, 'FORMOSO DO ARAGUAIA', 27, '1708205', 1),
+ (5480, 'FORTALEZA DO TABOCAO', 27, '1708254', 1),
+ (5481, 'GOIANORTE', 27, '1708304', 1),
+ (5482, 'GOIATINS', 27, '1709005', 1),
+ (5483, 'GUARAI', 27, '1709302', 1),
+ (5484, 'GURUPI', 27, '1709500', 1),
+ (5485, 'IPUEIRAS', 27, '1709807', 1),
+ (5486, 'ITACAJA', 27, '1710508', 1),
+ (5487, 'ITAGUATINS', 27, '1710706', 1),
+ (5488, 'ITAPIRATINS', 27, '1710904', 1),
+ (5489, 'ITAPORA DO TOCANTINS', 27, '1711100', 1),
+ (5490, 'JAU DO TOCANTINS', 27, '1711506', 1),
+ (5491, 'JUARINA', 27, '1711803', 1),
+ (5492, 'LAGOA DA CONFUSAO', 27, '1711902', 1),
+ (5493, 'LAGOA DO TOCANTINS', 27, '1711951', 1),
+ (5494, 'LAJEADO', 27, '1712009', 1),
+ (5495, 'LAVANDEIRA', 27, '1712157', 1),
+ (5496, 'LIZARDA', 27, '1712405', 1),
+ (5497, 'LUZINOPOLIS', 27, '1712454', 1),
+ (5498, 'MARIANOPOLIS DO TOCANTINS', 27, '1712504', 1),
+ (5499, 'MATEIROS', 27, '1712702', 1),
+ (5500, 'MAURILANDIA DO TOCANTINS', 27, '1712801', 1),
+ (5501, 'MIRACEMA DO TOCANTINS', 27, '1713205', 1),
+ (5502, 'MIRANORTE', 27, '1713304', 1),
+ (5503, 'MONTE DO CARMO', 27, '1713601', 1),
+ (5504, 'MONTE SANTO DO TOCANTINS', 27, '1713700', 1),
+ (5505, 'PALMEIRAS DO TOCANTINS', 27, '1713809', 1),
+ (5506, 'MURICILANDIA', 27, '1713957', 1),
+ (5507, 'NATIVIDADE', 27, '1714203', 1),
+ (5508, 'NAZARE', 27, '1714302', 1),
+ (5509, 'NOVA OLINDA', 27, '1714880', 1),
+ (5510, 'NOVA ROSALANDIA', 27, '1715002', 1),
+ (5511, 'NOVO ACORDO', 27, '1715101', 1),
+ (5512, 'NOVO ALEGRE', 27, '1715150', 1),
+ (5513, 'NOVO JARDIM', 27, '1715259', 1),
+ (5514, 'OLIVEIRA DE FATIMA', 27, '1715507', 1),
+ (5515, 'PALMEIRANTE', 27, '1715705', 1),
+ (5516, 'PALMEIROPOLIS', 27, '1715754', 1),
+ (5517, 'PARAISO DO TOCANTINS', 27, '1716109', 1),
+ (5518, 'PARANA', 27, '1716208', 1),
+ (5519, 'PAU DARCO', 27, '1716307', 1),
+ (5520, 'PEDRO AFONSO', 27, '1716505', 1),
+ (5521, 'PEIXE', 27, '1716604', 1),
+ (5522, 'PEQUIZEIRO', 27, '1716653', 1),
+ (5523, 'COLMEIA', 27, '1716703', 1),
+ (5524, 'PINDORAMA DO TOCANTINS', 27, '1717008', 1),
+ (5525, 'PIRAQUE', 27, '1717206', 1),
+ (5526, 'PIUM', 27, '1717503', 1),
+ (5527, 'PONTE ALTA DO BOM JESUS', 27, '1717800', 1),
+ (5528, 'PONTE ALTA DO TOCANTINS', 27, '1717909', 1),
+ (5529, 'PORTO ALEGRE DO TOCANTINS', 27, '1718006', 1),
+ (5530, 'PORTO NACIONAL', 27, '1718204', 1),
+ (5531, 'PRAIA NORTE', 27, '1718303', 1),
+ (5532, 'PRESIDENTE KENNEDY', 27, '1718402', 1),
+ (5533, 'PUGMIL', 27, '1718451', 1),
+ (5534, 'RECURSOLANDIA', 27, '1718501', 1),
+ (5535, 'RIACHINHO', 27, '1718550', 1),
+ (5536, 'RIO DA CONCEICAO', 27, '1718659', 1),
+ (5537, 'RIO DOS BOIS', 27, '1718709', 1),
+ (5538, 'RIO SONO', 27, '1718758', 1),
+ (5539, 'SAMPAIO', 27, '1718808', 1),
+ (5540, 'SANDOLANDIA', 27, '1718840', 1),
+ (5541, 'SANTA FE DO ARAGUAIA', 27, '1718865', 1),
+ (5542, 'SANTA MARIA DO TOCANTINS', 27, '1718881', 1),
+ (5543, 'SANTA RITA DO TOCANTINS', 27, '1718899', 1),
+ (5544, 'SANTA ROSA DO TOCANTINS', 27, '1718907', 1),
+ (5545, 'SANTA TEREZA DO TOCANTINS', 27, '1719004', 1),
+ (5546, 'SANTA TEREZINHA DO TOCANTINS', 27, '1720002', 1),
+ (5547, 'SAO BENTO DO TOCANTINS', 27, '1720101', 1),
+ (5548, 'SAO FELIX DO TOCANTINS', 27, '1720150', 1),
+ (5549, 'SAO MIGUEL DO TOCANTINS', 27, '1720200', 1),
+ (5550, 'SAO SALVADOR DO TOCANTINS', 27, '1720259', 1),
+ (5551, 'SAO SEBASTIAO DO TOCANTINS', 27, '1720309', 1),
+ (5552, 'SAO VALERIO', 27, '1720499', 1),
+ (5553, 'SILVANOPOLIS', 27, '1720655', 1),
+ (5554, 'SITIO NOVO DO TOCANTINS', 27, '1720804', 1),
+ (5555, 'SUCUPIRA', 27, '1720853', 1),
+ (5556, 'TAGUATINGA', 27, '1720903', 1),
+ (5557, 'TAIPAS DO TOCANTINS', 27, '1720937', 1),
+ (5558, 'TALISMA', 27, '1720978', 1),
+ (5559, 'PALMAS', 27, '1721000', 1),
+ (5560, 'TOCANTINIA', 27, '1721109', 1),
+ (5561, 'TOCANTINOPOLIS', 27, '1721208', 1),
+ (5562, 'TUPIRAMA', 27, '1721257', 1),
+ (5563, 'TUPIRATINS', 27, '1721307', 1),
+ (5564, 'WANDERLANDIA', 27, '1722081', 1),
+ (5565, 'XAMBIOA', 27, '1722107', 1);
+/*!40000 ALTER TABLE `tab_city` ENABLE KEYS */;
+
diff --git a/sql/0002-db-version.sql b/sql/0002-db-version.sql
new file mode 100644
index 0000000..89b64b1
--- /dev/null
+++ b/sql/0002-db-version.sql
@@ -0,0 +1,36 @@
+CREATE TABLE IF NOT EXISTS `tab_db_version` (
+ `db_version_id` INT NOT NULL AUTO_INCREMENT,
+ `db_version` VARCHAR(100) NOT NULL,
+ `db_version_create_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `db_version_update_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`db_version_id`),
+ UNIQUE INDEX `uq_tab_db_version_db_version` (`db_version` ASC));
+
+DELIMITER $$
+
+DROP PROCEDURE IF EXISTS `sp_set_db_version`$$
+
+CREATE PROCEDURE `sp_set_db_version`(
+ IN `script_name` VARCHAR(100)
+)
+LANGUAGE SQL
+DETERMINISTIC
+MODIFIES SQL DATA
+SQL SECURITY INVOKER
+COMMENT 'Sets a DB version'
+BEGIN
+ IF (script_name NOT LIKE '%.sql') THEN
+ SET script_name = CONCAT(script_name, '.sql');
+ END IF;
+
+ INSERT INTO `tab_db_version`(`db_version`)
+ VALUES(script_name)
+ ON DUPLICATE KEY UPDATE
+ `db_version` = VALUES(`db_version`);
+END$$
+
+DELIMITER ;
+
+call `sp_set_db_version`('0000-initial-db-structure');
+call `sp_set_db_version`('0001-initial-db-load');
+call `sp_set_db_version`('0002-db-version');
diff --git a/sql/0003-create-users-table.sql b/sql/0003-create-users-table.sql
new file mode 100644
index 0000000..07c00cb
--- /dev/null
+++ b/sql/0003-create-users-table.sql
@@ -0,0 +1,11 @@
+CREATE TABLE IF NOT EXISTS `db_boilerplate`.`tab_users` (
+ `user_id` INT NOT NULL AUTO_INCREMENT,
+ `user_name` VARCHAR(50) NOT NULL,
+ `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `active` TINYINT(1) NOT NULL DEFAULT 1,
+
+ PRIMARY KEY (`user_id`)
+)
+
+ ENGINE = InnoDB;
\ No newline at end of file
diff --git a/sql/0004-db-version.sql b/sql/0004-db-version.sql
new file mode 100644
index 0000000..9e16898
--- /dev/null
+++ b/sql/0004-db-version.sql
@@ -0,0 +1,39 @@
+CREATE TABLE IF NOT EXISTS `tab_db_version` (
+ `db_version_id` INT NOT NULL AUTO_INCREMENT,
+ `db_version` VARCHAR(100) NOT NULL,
+ `db_version_create_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `db_version_update_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`db_version_id`),
+ UNIQUE INDEX `uq_tab_db_version_db_version` (`db_version` ASC));
+
+DELIMITER $$
+
+DROP PROCEDURE IF EXISTS `sp_set_db_version`$$
+
+CREATE PROCEDURE `sp_set_db_version`(
+ IN `script_name` VARCHAR(100)
+)
+LANGUAGE SQL
+DETERMINISTIC
+MODIFIES SQL DATA
+SQL SECURITY INVOKER
+COMMENT 'Sets a DB version'
+BEGIN
+ IF (script_name NOT LIKE '%.sql') THEN
+ SET script_name = CONCAT(script_name, '.sql');
+ END IF;
+
+ INSERT INTO `tab_db_version`(`db_version`)
+ VALUES(script_name)
+ ON DUPLICATE KEY UPDATE
+ `db_version` = VALUES(`db_version`);
+END$$
+
+DELIMITER ;
+
+call `sp_set_db_version`('0000-initial-db-structure');
+call `sp_set_db_version`('0001-initial-db-load');
+call `sp_set_db_version`('0002-db-version');
+
+call `sp_set_db_version`('0003-create-users-table');
+call `sp_set_db_version`('0004-db-version');
diff --git a/static/cert/nemt-portal-api.crt b/static/cert/nemt-portal-api.crt
new file mode 100644
index 0000000..7918d3f
--- /dev/null
+++ b/static/cert/nemt-portal-api.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDdjCCAl4CCQDq8tDDIwVZAjANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJC
+UjETMBEGA1UECBQKU8OjbyBQYXVsbzETMBEGA1UEBxQKU8OjbyBQYXVsbzEVMBMG
+A1UEChMMUmVkIFZlbnR1cmVzMQ8wDQYDVQQLEwZCcmF6aWwxHDAaBgNVBAMTE2Jh
+Y2thcGktYm9pbGVycGxhdGUwHhcNMTcwNzE0MjIwMzEzWhcNMTgwNzE0MjIwMzEz
+WjB9MQswCQYDVQQGEwJCUjETMBEGA1UECBQKU8OjbyBQYXVsbzETMBEGA1UEBxQK
+U8OjbyBQYXVsbzEVMBMGA1UEChMMUmVkIFZlbnR1cmVzMQ8wDQYDVQQLEwZCcmF6
+aWwxHDAaBgNVBAMTE2JhY2thcGktYm9pbGVycGxhdGUwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDJiWXq2vXyA+Fv6VLg8mXLbd9JtQKvlnlZB7+zno+/
+5AakEnnjI5uxv7kFQ+OwnEFJt1fk54cclnXStrnySbdtLCJ/6ttE+ck7xshQCRap
+wEL4oVPua9JGDhZiTN+/T/Huh0mPm73VmeFEKcTpBwQKPHOzZ52Bjfk6IxO5+d5g
+yrTqJOUnwuXnCjZOxmqICoGO1Ty9BKZqCfjq82vqovRfmSnUucDotpT3dWZiZrqv
+EL+s8U0hdF0pTnCXLySLZVrzERg3+XZ2DOeT/Bn2vIWuFmFlCjgTXZHkHGBCIxJx
+vnZSk+cPZl+andhN6DjCOiCuZd2BiEd1XuwDGk8Iksr3AgMBAAEwDQYJKoZIhvcN
+AQEFBQADggEBALtTjB0rbJ1yG22dyXHIGx1YJn5yiyzYI3GGvrJRoE37hxRMLUie
+Th6UZb0NDJwuxaViAWQjH3uJXnTMQkxsEyoyoPt9fB5bQrTkBCUYvIE8m48zmLEk
+9HkB4qvhVy2QjLuehNloLGL5ug+eLrIgVUIPSFmCuIYJ50aGq1Yjd1732Eer4Qeu
+zbX8sj4PAF9FofgwS9W4LTTHAokT2WytuZJQhyHQpJiNeEx+FtddqkAEeKeP46c5
+UzxFhUjmTFzM3/A1I7wevKwC58XFWnogyFG0DtnTJmr7tjVYNl6oa6FvAfuyiE7+
+PLJ2jidg3hY86Jyib7FSeZ+GNbj/g1jqPdQ=
+-----END CERTIFICATE-----
diff --git a/static/cert/nemt-portal-api.key b/static/cert/nemt-portal-api.key
new file mode 100644
index 0000000..5d9d829
--- /dev/null
+++ b/static/cert/nemt-portal-api.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAyYll6tr18gPhb+lS4PJly23fSbUCr5Z5WQe/s56Pv+QGpBJ5
+4yObsb+5BUPjsJxBSbdX5OeHHJZ10ra58km3bSwif+rbRPnJO8bIUAkWqcBC+KFT
+7mvSRg4WYkzfv0/x7odJj5u91ZnhRCnE6QcECjxzs2edgY35OiMTufneYMq06iTl
+J8Ll5wo2TsZqiAqBjtU8vQSmagn46vNr6qL0X5kp1LnA6LaU93VmYma6rxC/rPFN
+IXRdKU5wly8ki2Va8xEYN/l2dgznk/wZ9ryFrhZhZQo4E12R5BxgQiMScb52UpPn
+D2Zfmp3YTeg4wjogrmXdgYhHdV7sAxpPCJLK9wIDAQABAoIBAQDHYYrWofCXkYdB
+9A7uRGC4tOYmQVF67N74WVYqGUAVkz2OrEixkdTCMO6WauejHbLpft0RtIxSl/fQ
+kr27GXrCItuuuWZcAtI2tR4PMC6fmXmoB9LFGR5Z+C3k6jChUDIEzQrVbDqOS0I0
+8S3BbBNvHQdKAcQtG4vpHDKz1qNOFPsFWnTRLfVC68UzyfBLFdPORACLV6gzae9I
+QW+n5V7f3MsIslU1bAS6uQ+hDOmOLjZ4mLFbrRILEMVzNOzvLPIRLY8WUGHRUq6+
+PsR5yoJPR9NvcFkUIW0AUbl++jZgFZBQb5a/IconDHKU1+7mB6hk+2BBGBx5ueNo
+5W1E6YeBAoGBAOgWnj9VyWX+anwz5XmopuSlilj/CL5C4G0R6QYcYv3LKNqAGi7i
+UGwawqFY8cxdeAE/a9YFnj4y+ZAnlg2lfF3NqCd2CnoTs86BquThLfs5mQMJRNGn
+8ThgR8tGWWekbWv4R8m3/nI0tM+CJ/xfsljlMlfM2qO9gTjfN5jXaynHAoGBAN5M
++UEGuvqC/Mhufm9wciG4WUAzdOuBQcNeqxE5pJb1vrbSHVgIEX82EVlMwGYR8vBn
+XXfJUhAlr4vYUQ3I48GYc+Jq2WU3St4YH5Kk005iceRCpOkQLFVWqlu2fHZXkya5
+4ZLV9W8Lk20UrSBkBUyTqVqqhYBlcfdrzoja2NVRAoGBAKbmRQy0y20uZTNGOrqf
+Xs1EglX3qTjxbOTioVmEpmduZsWio7GdjEoBgH95MAFQIhF7oze4uJBwJenVneHY
+ZLQsRcWC7IvXiVFzDAsmJ+PnCrMVQkkm5aAuFNMIlxiiNRIU7MMSLsfAQVqMdebW
+hrHIuMhNB9oCWGAmnZurJmRXAoGAVH9vsx7qzbQif9E4MAXO7DBVhIjKpYYBSFDg
+t3Bwtoz8jCN70e1nMTKND6OT8nhaHrU7mv+kOM0KWB7GWHYG1JytV+ADeGy3AYqr
+3aLXSxEyd3A5nPlv0JRbtva7goQxQ+Qd8SFw5F/DDxBv6kL6nKv4EKWGj1KAKmsJ
+G44MI7ECgYEAuKDpwV/j3ibBMhuLNJQOBl6RoD6ogmHeP6k9d+nEQYS6HbVcj86s
+fxuF6fFRGSSqCZfCmNThRNsFWyXYtLHqvKnqMq9RA0LzJVNPfDpMjs6cRUNjbgQl
+jaYZ5zSaIAQ5o5gjnBsXmhkQTMQm+LBsAk9NAYICC2ISJROqIROXrwE=
+-----END RSA PRIVATE KEY-----
diff --git a/static/swagger-ui/favicon-16x16.png b/static/swagger-ui/favicon-16x16.png
new file mode 100755
index 0000000..0f7e13b
Binary files /dev/null and b/static/swagger-ui/favicon-16x16.png differ
diff --git a/static/swagger-ui/favicon-32x32.png b/static/swagger-ui/favicon-32x32.png
new file mode 100755
index 0000000..b0a3352
Binary files /dev/null and b/static/swagger-ui/favicon-32x32.png differ
diff --git a/static/swagger-ui/index.html b/static/swagger-ui/index.html
new file mode 100755
index 0000000..5fd6ff5
--- /dev/null
+++ b/static/swagger-ui/index.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ Swagger UI
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/static/swagger-ui/oauth2-redirect.html b/static/swagger-ui/oauth2-redirect.html
new file mode 100755
index 0000000..4de4053
--- /dev/null
+++ b/static/swagger-ui/oauth2-redirect.html
@@ -0,0 +1,53 @@
+
+
+
+
+
+
diff --git a/static/swagger-ui/swagger-ui-bundle.js b/static/swagger-ui/swagger-ui-bundle.js
new file mode 100755
index 0000000..73c9be6
--- /dev/null
+++ b/static/swagger-ui/swagger-ui-bundle.js
@@ -0,0 +1,112 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUIBundle=t():e.SwaggerUIBundle=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="/dist",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,i){r.apply(this,[e,t,i].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){n(1),e.exports=n(298)},function(e,t,n){(function(e){"use strict";function t(e,t,n){e[t]||Object[r](e,t,{writable:!0,configurable:!0,value:n})}if(n(2),n(293),n(295),e._babelPolyfill)throw new Error("only one instance of babel-polyfill is allowed");e._babelPolyfill=!0;var r="defineProperty";t(String.prototype,"padLeft","".padStart),t(String.prototype,"padRight","".padEnd),"pop,reverse,shift,keys,values,entries,indexOf,every,some,forEach,map,filter,find,findIndex,includes,join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill".split(",").forEach(function(e){[][e]&&t(Array,e,Function.call.bind([][e]))})}).call(t,function(){return this}())},function(e,t,n){n(3),n(52),n(53),n(54),n(55),n(57),n(60),n(61),n(62),n(63),n(64),n(65),n(66),n(67),n(68),n(70),n(72),n(74),n(76),n(79),n(80),n(81),n(85),n(87),n(89),n(92),n(93),n(94),n(95),n(97),n(98),n(99),n(100),n(101),n(102),n(103),n(105),n(106),n(107),n(109),n(110),n(111),n(113),n(114),n(115),n(116),n(117),n(118),n(119),n(120),n(121),n(122),n(123),n(124),n(125),n(126),n(131),n(132),n(136),n(137),n(138),n(139),n(141),n(142),n(143),n(144),n(145),n(146),n(147),n(148),n(149),n(150),n(151),n(152),n(153),n(154),n(155),n(156),n(157),n(159),n(160),n(166),n(167),n(169),n(170),n(171),n(175),n(176),n(177),n(178),n(179),n(181),n(182),n(183),n(184),n(187),n(189),n(190),n(191),n(193),n(195),n(197),n(198),n(199),n(201),n(202),n(203),n(204),n(211),n(214),n(215),n(217),n(218),n(221),n(222),n(224),n(225),n(226),n(227),n(228),n(229),n(230),n(231),n(232),n(233),n(234),n(235),n(236),n(237),n(238),n(239),n(240),n(241),n(242),n(244),n(245),n(246),n(247),n(248),n(249),n(251),n(252),n(253),n(254),n(255),n(256),n(257),n(258),n(260),n(261),n(263),n(264),n(265),n(266),n(269),n(270),n(271),n(272),n(273),n(274),n(275),n(276),n(278),n(279),n(280),n(281),n(282),n(283),n(284),n(285),n(286),n(287),n(288),n(291),n(292),e.exports=n(9)},[1368,4,5,6,8,18,22,7,23,24,19,25,26,27,29,42,45,12,32,16,17,46,49,51,11,30,50,44,43,28,10],function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},[1369,7],function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){var r=n(4),i=n(9),o=n(10),a=n(18),s=n(20),u="prototype",c=function(e,t,n){var l,p,f,h,d=e&c.F,m=e&c.G,y=e&c.S,v=e&c.P,g=e&c.B,_=m?r:y?r[t]||(r[t]={}):(r[t]||{})[u],b=m?i:i[t]||(i[t]={}),w=b[u]||(b[u]={});m&&(n=t);for(l in n)p=!d&&_&&void 0!==_[l],f=(p?_:n)[l],h=g&&p?s(f,r):v&&"function"==typeof f?s(Function.call,f):f,_&&a(_,l,f,e&c.U),b[l]!=f&&o(b,l,h),v&&w[l]!=f&&(w[l]=f)};r.core=i,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,t){var n=e.exports={version:"2.4.0"};"number"==typeof __e&&(__e=n)},[1370,11,17,6],[1371,12,14,16,6],[1372,13],function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},[1373,6,7,15],[1374,13,4],[1375,13],function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){var r=n(4),i=n(10),o=n(5),a=n(19)("src"),s="toString",u=Function[s],c=(""+u).split(s);n(9).inspectSource=function(e){return u.call(e)},(e.exports=function(e,t,n,s){var u="function"==typeof n;u&&(o(n,"name")||i(n,"name",t)),e[t]!==n&&(u&&(o(n,a)||i(n,a,e[t]?""+e[t]:c.join(String(t)))),e===r?e[t]=n:s?e[t]?e[t]=n:i(e,t,n):(delete e[t],i(e,t,n)))})(Function.prototype,s,function(){return"function"==typeof this&&this[a]||u.call(this)})},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},[1376,21],function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},[1377,19,13,5,11,7],[1378,4],[1379,11,5,25],[1380,23,19,4],[1381,25],[1382,4,9,28,26,11],function(e,t){e.exports=!1},[1383,30,32],[1384,31,41],[1385,5,32,36,40],[1386,33,35],[1387,34],function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},[1388,32,37,39],[1389,38],function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},[1390,38],[1391,23,19],function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},[1392,30,43,44],function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t){t.f={}.propertyIsEnumerable},[1393,34],[1394,12,47,41,40,15,48],[1395,11,12,30,6],[1396,4],[1397,32,50],[1398,31,41],[1399,44,17,32,16,5,14,6],[1400,8,46],[1401,8,6,11],function(e,t,n){var r=n(8);r(r.S+r.F*!n(6),"Object",{defineProperties:n(47)})},function(e,t,n){var r=n(32),i=n(51).f;n(56)("getOwnPropertyDescriptor",function(){return function(e,t){return i(r(e),t)}})},[1402,8,9,7],function(e,t,n){var r=n(58),i=n(59);n(56)("getPrototypeOf",function(){return function(e){return i(r(e))}})},[1403,35],[1404,5,58,40],[1405,58,30,56],function(e,t,n){n(56)("getOwnPropertyNames",function(){return n(49).f})},function(e,t,n){var r=n(13),i=n(22).onFreeze;n(56)("freeze",function(e){return function(t){return e&&r(t)?e(i(t)):t}})},function(e,t,n){var r=n(13),i=n(22).onFreeze;n(56)("seal",function(e){return function(t){return e&&r(t)?e(i(t)):t}})},function(e,t,n){var r=n(13),i=n(22).onFreeze;n(56)("preventExtensions",function(e){return function(t){return e&&r(t)?e(i(t)):t}})},function(e,t,n){var r=n(13);n(56)("isFrozen",function(e){return function(t){return!r(t)||!!e&&e(t)}})},function(e,t,n){var r=n(13);n(56)("isSealed",function(e){return function(t){return!r(t)||!!e&&e(t)}})},function(e,t,n){var r=n(13);n(56)("isExtensible",function(e){return function(t){return!!r(t)&&(!e||e(t))}})},[1406,8,69],[1407,30,43,44,58,33,7],function(e,t,n){var r=n(8);r(r.S,"Object",{is:n(71)})},function(e,t){e.exports=Object.is||function(e,t){return e===t?0!==e||1/e===1/t:e!=e&&t!=t}},function(e,t,n){var r=n(8);r(r.S,"Object",{setPrototypeOf:n(73).set})},function(e,t,n){var r=n(13),i=n(12),o=function(e,t){if(i(e),!r(t)&&null!==t)throw TypeError(t+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,t,r){try{r=n(20)(Function.call,n(51).f(Object.prototype,"__proto__").set,2),r(e,[]),t=!(e instanceof Array)}catch(e){t=!0}return function(e,n){return o(e,n),t?e.__proto__=n:r(e,n),e}}({},!1):void 0),check:o}},function(e,t,n){"use strict";var r=n(75),i={};i[n(25)("toStringTag")]="z",i+""!="[object z]"&&n(18)(Object.prototype,"toString",function(){return"[object "+r(this)+"]"},!0)},[1408,34,25],function(e,t,n){var r=n(8);r(r.P,"Function",{bind:n(77)})},function(e,t,n){"use strict";var r=n(21),i=n(13),o=n(78),a=[].slice,s={},u=function(e,t,n){if(!(t in s)){for(var r=[],i=0;i>>0||(a.test(n)?16:10))}:r},function(e,t,n){var r=n(8),i=n(35),o=n(7),a=n(84),s="["+a+"]",u="
",c=RegExp("^"+s+s+"*"),l=RegExp(s+s+"*$"),p=function(e,t,n){var i={},s=o(function(){return!!a[e]()||u[e]()!=u}),c=i[e]=s?t(f):a[e];n&&(i[n]=c),r(r.P+r.F*s,"String",i)},f=p.trim=function(e,t){return e=String(i(e)),1&t&&(e=e.replace(c,"")),2&t&&(e=e.replace(l,"")),e};e.exports=p},function(e,t){e.exports="\t\n\v\f\r \u2028\u2029\ufeff"},function(e,t,n){var r=n(8),i=n(86);r(r.G+r.F*(parseFloat!=i),{parseFloat:i})},function(e,t,n){var r=n(4).parseFloat,i=n(83).trim;e.exports=1/r(n(84)+"-0")!==-(1/0)?function(e){var t=i(String(e),3),n=r(t);return 0===n&&"-"==t.charAt(0)?-0:n}:r},function(e,t,n){"use strict";var r=n(4),i=n(5),o=n(34),a=n(88),s=n(16),u=n(7),c=n(50).f,l=n(51).f,p=n(11).f,f=n(83).trim,h="Number",d=r[h],m=d,y=d.prototype,v=o(n(46)(y))==h,g="trim"in String.prototype,_=function(e){var t=s(e,!1);if("string"==typeof t&&t.length>2){t=g?t.trim():f(t,3);var n,r,i,o=t.charCodeAt(0);if(43===o||45===o){if(n=t.charCodeAt(2),88===n||120===n)return NaN}else if(48===o){switch(t.charCodeAt(1)){case 66:case 98:r=2,i=49;break;case 79:case 111:r=8,i=55;break;default:return+t}for(var a,u=t.slice(2),c=0,l=u.length;ci)return NaN;return parseInt(u,r)}}return+t};if(!d(" 0o1")||!d("0b1")||d("+0x1")){d=function(e){var t=arguments.length<1?0:e,n=this;return n instanceof d&&(v?u(function(){y.valueOf.call(n)}):o(n)!=h)?a(new m(_(t)),n,d):_(t)};for(var b,w=n(6)?c(m):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),x=0;w.length>x;x++)i(m,b=w[x])&&!i(d,b)&&p(d,b,l(m,b));d.prototype=y,y.constructor=d,n(18)(r,h,d)}},function(e,t,n){var r=n(13),i=n(73).set;e.exports=function(e,t,n){var o,a=t.constructor;return a!==n&&"function"==typeof a&&(o=a.prototype)!==n.prototype&&r(o)&&i&&i(e,o),e}},function(e,t,n){"use strict";var r=n(8),i=n(38),o=n(90),a=n(91),s=1..toFixed,u=Math.floor,c=[0,0,0,0,0,0],l="Number.toFixed: incorrect invocation!",p="0",f=function(e,t){for(var n=-1,r=t;++n<6;)r+=e*c[n],c[n]=r%1e7,r=u(r/1e7)},h=function(e){for(var t=6,n=0;--t>=0;)n+=c[t],c[t]=u(n/e),n=n%e*1e7},d=function(){for(var e=6,t="";--e>=0;)if(""!==t||0===e||0!==c[e]){var n=String(c[e]);t=""===t?n:t+a.call(p,7-n.length)+n}return t},m=function(e,t,n){return 0===t?n:t%2===1?m(e,t-1,n*e):m(e*e,t/2,n)},y=function(e){for(var t=0,n=e;n>=4096;)t+=12,n/=4096;for(;n>=2;)t+=1,n/=2;return t};r(r.P+r.F*(!!s&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==(0xde0b6b3a7640080).toFixed(0))||!n(7)(function(){s.call({})})),"Number",{toFixed:function(e){var t,n,r,s,u=o(this,l),c=i(e),v="",g=p;if(c<0||c>20)throw RangeError(l);if(u!=u)return"NaN";if(u<=-1e21||u>=1e21)return String(u);if(u<0&&(v="-",u=-u),u>1e-21)if(t=y(u*m(2,69,1))-69,n=t<0?u*m(2,-t,1):u/m(2,t,1),n*=4503599627370496,t=52-t,t>0){for(f(0,n),r=c;r>=7;)f(1e7,0),r-=7;for(f(m(10,r,1),0),r=t-1;r>=23;)h(1<<23),r-=23;h(1<0?(s=g.length,g=v+(s<=c?"0."+a.call(p,c-s)+g:g.slice(0,s-c)+"."+g.slice(s-c))):g=v+g,g}})},function(e,t,n){var r=n(34);e.exports=function(e,t){if("number"!=typeof e&&"Number"!=r(e))throw TypeError(t);return+e}},function(e,t,n){"use strict";var r=n(38),i=n(35);e.exports=function(e){var t=String(i(this)),n="",o=r(e);if(o<0||o==1/0)throw RangeError("Count can't be negative");for(;o>0;(o>>>=1)&&(t+=t))1&o&&(n+=t);return n}},function(e,t,n){"use strict";var r=n(8),i=n(7),o=n(90),a=1..toPrecision;r(r.P+r.F*(i(function(){return"1"!==a.call(1,void 0)})||!i(function(){a.call({})})),"Number",{toPrecision:function(e){var t=o(this,"Number#toPrecision: incorrect invocation!");return void 0===e?a.call(t):a.call(t,e)}})},function(e,t,n){var r=n(8);r(r.S,"Number",{EPSILON:Math.pow(2,-52)})},function(e,t,n){var r=n(8),i=n(4).isFinite;r(r.S,"Number",{isFinite:function(e){return"number"==typeof e&&i(e)}})},function(e,t,n){var r=n(8);r(r.S,"Number",{isInteger:n(96)})},function(e,t,n){var r=n(13),i=Math.floor;e.exports=function(e){return!r(e)&&isFinite(e)&&i(e)===e}},function(e,t,n){var r=n(8);r(r.S,"Number",{isNaN:function(e){return e!=e}})},function(e,t,n){var r=n(8),i=n(96),o=Math.abs;r(r.S,"Number",{isSafeInteger:function(e){return i(e)&&o(e)<=9007199254740991}})},function(e,t,n){var r=n(8);r(r.S,"Number",{MAX_SAFE_INTEGER:9007199254740991})},function(e,t,n){var r=n(8);r(r.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991})},function(e,t,n){var r=n(8),i=n(86);r(r.S+r.F*(Number.parseFloat!=i),"Number",{parseFloat:i})},function(e,t,n){var r=n(8),i=n(82);r(r.S+r.F*(Number.parseInt!=i),"Number",{parseInt:i})},function(e,t,n){var r=n(8),i=n(104),o=Math.sqrt,a=Math.acosh;r(r.S+r.F*!(a&&710==Math.floor(a(Number.MAX_VALUE))&&a(1/0)==1/0),"Math",{acosh:function(e){return(e=+e)<1?NaN:e>94906265.62425156?Math.log(e)+Math.LN2:i(e-1+o(e-1)*o(e+1))}})},function(e,t){e.exports=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:Math.log(1+e)}},function(e,t,n){function r(e){return isFinite(e=+e)&&0!=e?e<0?-r(-e):Math.log(e+Math.sqrt(e*e+1)):e}var i=n(8),o=Math.asinh;i(i.S+i.F*!(o&&1/o(0)>0),"Math",{asinh:r})},function(e,t,n){var r=n(8),i=Math.atanh;r(r.S+r.F*!(i&&1/i(-0)<0),"Math",{atanh:function(e){return 0==(e=+e)?e:Math.log((1+e)/(1-e))/2}})},function(e,t,n){var r=n(8),i=n(108);r(r.S,"Math",{cbrt:function(e){return i(e=+e)*Math.pow(Math.abs(e),1/3)}})},function(e,t){e.exports=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1}},function(e,t,n){var r=n(8);r(r.S,"Math",{clz32:function(e){return(e>>>=0)?31-Math.floor(Math.log(e+.5)*Math.LOG2E):32}})},function(e,t,n){var r=n(8),i=Math.exp;r(r.S,"Math",{cosh:function(e){return(i(e=+e)+i(-e))/2}})},function(e,t,n){var r=n(8),i=n(112);r(r.S+r.F*(i!=Math.expm1),"Math",{expm1:i})},function(e,t){var n=Math.expm1;e.exports=!n||n(10)>22025.465794806718||n(10)<22025.465794806718||n(-2e-17)!=-2e-17?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:Math.exp(e)-1}:n},function(e,t,n){var r=n(8),i=n(108),o=Math.pow,a=o(2,-52),s=o(2,-23),u=o(2,127)*(2-s),c=o(2,-126),l=function(e){return e+1/a-1/a};r(r.S,"Math",{fround:function(e){var t,n,r=Math.abs(e),o=i(e);return ru||n!=n?o*(1/0):o*n)}})},function(e,t,n){var r=n(8),i=Math.abs;r(r.S,"Math",{hypot:function(e,t){for(var n,r,o=0,a=0,s=arguments.length,u=0;a0?(r=n/u,o+=r*r):o+=n;return u===1/0?1/0:u*Math.sqrt(o)}})},function(e,t,n){var r=n(8),i=Math.imul;r(r.S+r.F*n(7)(function(){return i(4294967295,5)!=-5||2!=i.length}),"Math",{imul:function(e,t){var n=65535,r=+e,i=+t,o=n&r,a=n&i;return 0|o*a+((n&r>>>16)*a+o*(n&i>>>16)<<16>>>0)}})},function(e,t,n){var r=n(8);r(r.S,"Math",{log10:function(e){return Math.log(e)/Math.LN10}})},function(e,t,n){var r=n(8);r(r.S,"Math",{log1p:n(104)})},function(e,t,n){var r=n(8);r(r.S,"Math",{log2:function(e){return Math.log(e)/Math.LN2}})},function(e,t,n){var r=n(8);r(r.S,"Math",{sign:n(108)})},function(e,t,n){var r=n(8),i=n(112),o=Math.exp;r(r.S+r.F*n(7)(function(){return!Math.sinh(-2e-17)!=-2e-17}),"Math",{sinh:function(e){return Math.abs(e=+e)<1?(i(e)-i(-e))/2:(o(e-1)-o(-e-1))*(Math.E/2)}})},function(e,t,n){var r=n(8),i=n(112),o=Math.exp;r(r.S,"Math",{tanh:function(e){var t=i(e=+e),n=i(-e);return t==1/0?1:n==1/0?-1:(t-n)/(o(e)+o(-e))}})},function(e,t,n){var r=n(8);r(r.S,"Math",{trunc:function(e){return(e>0?Math.floor:Math.ceil)(e)}})},function(e,t,n){var r=n(8),i=n(39),o=String.fromCharCode,a=String.fromCodePoint;r(r.S+r.F*(!!a&&1!=a.length),"String",{fromCodePoint:function(e){for(var t,n=[],r=arguments.length,a=0;r>a;){if(t=+arguments[a++],i(t,1114111)!==t)throw RangeError(t+" is not a valid code point");n.push(t<65536?o(t):o(((t-=65536)>>10)+55296,t%1024+56320))}return n.join("")}})},function(e,t,n){var r=n(8),i=n(32),o=n(37);r(r.S,"String",{raw:function(e){for(var t=i(e.raw),n=o(t.length),r=arguments.length,a=[],s=0;n>s;)a.push(String(t[s++])),s1?arguments[1]:void 0,r=i(t.length),u=void 0===n?r:Math.min(i(n),r),c=String(e);return s?s.call(t,c,u):t.slice(u-c.length,u)===c}})},function(e,t,n){var r=n(134),i=n(35);e.exports=function(e,t,n){if(r(t))throw TypeError("String#"+n+" doesn't accept regex!");return String(i(e))}},function(e,t,n){var r=n(13),i=n(34),o=n(25)("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[o])?!!t:"RegExp"==i(e))}},function(e,t,n){var r=n(25)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[r]=!1,!"/./"[e](t)}catch(e){}}return!0}},function(e,t,n){"use strict";var r=n(8),i=n(133),o="includes";r(r.P+r.F*n(135)(o),"String",{includes:function(e){return!!~i(this,e,o).indexOf(e,arguments.length>1?arguments[1]:void 0)}})},function(e,t,n){var r=n(8);r(r.P,"String",{repeat:n(91)})},function(e,t,n){"use strict";var r=n(8),i=n(37),o=n(133),a="startsWith",s=""[a];r(r.P+r.F*n(135)(a),"String",{startsWith:function(e){var t=o(this,e,a),n=i(Math.min(arguments.length>1?arguments[1]:void 0,t.length)),r=String(e);return s?s.call(t,r,n):t.slice(n,n+r.length)===r}})},function(e,t,n){"use strict";n(140)("anchor",function(e){return function(t){return e(this,"a","name",t)}})},function(e,t,n){var r=n(8),i=n(7),o=n(35),a=/"/g,s=function(e,t,n,r){var i=String(o(e)),s="<"+t;return""!==n&&(s+=" "+n+'="'+String(r).replace(a,""")+'"'),s+">"+i+""+t+">"};e.exports=function(e,t){var n={};n[e]=t(s),r(r.P+r.F*i(function(){var t=""[e]('"');return t!==t.toLowerCase()||t.split('"').length>3}),"String",n)}},function(e,t,n){"use strict";n(140)("big",function(e){return function(){return e(this,"big","","")}})},function(e,t,n){"use strict";n(140)("blink",function(e){return function(){return e(this,"blink","","")}})},function(e,t,n){"use strict";n(140)("bold",function(e){return function(){return e(this,"b","","")}})},function(e,t,n){"use strict";n(140)("fixed",function(e){return function(){return e(this,"tt","","")}})},function(e,t,n){"use strict";n(140)("fontcolor",function(e){return function(t){return e(this,"font","color",t)}})},function(e,t,n){"use strict";n(140)("fontsize",function(e){return function(t){return e(this,"font","size",t)}})},function(e,t,n){"use strict";n(140)("italics",function(e){return function(){return e(this,"i","","")}})},function(e,t,n){"use strict";n(140)("link",function(e){return function(t){return e(this,"a","href",t)}})},function(e,t,n){"use strict";n(140)("small",function(e){return function(){return e(this,"small","","")}})},function(e,t,n){"use strict";n(140)("strike",function(e){return function(){return e(this,"strike","","")}})},function(e,t,n){"use strict";n(140)("sub",function(e){return function(){return e(this,"sub","","")}})},function(e,t,n){"use strict";n(140)("sup",function(e){return function(){return e(this,"sup","","")}})},function(e,t,n){var r=n(8);r(r.S,"Date",{now:function(){return(new Date).getTime()}})},function(e,t,n){"use strict";var r=n(8),i=n(58),o=n(16);r(r.P+r.F*n(7)(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}),"Date",{toJSON:function(e){var t=i(this),n=o(t);return"number"!=typeof n||isFinite(n)?t.toISOString():null}})},function(e,t,n){"use strict";var r=n(8),i=n(7),o=Date.prototype.getTime,a=function(e){return e>9?e:"0"+e};r(r.P+r.F*(i(function(){return"0385-07-25T07:06:39.999Z"!=new Date(-5e13-1).toISOString()})||!i(function(){new Date(NaN).toISOString()})),"Date",{toISOString:function(){if(!isFinite(o.call(this)))throw RangeError("Invalid time value");var e=this,t=e.getUTCFullYear(),n=e.getUTCMilliseconds(),r=t<0?"-":t>9999?"+":"";return r+("00000"+Math.abs(t)).slice(r?-6:-4)+"-"+a(e.getUTCMonth()+1)+"-"+a(e.getUTCDate())+"T"+a(e.getUTCHours())+":"+a(e.getUTCMinutes())+":"+a(e.getUTCSeconds())+"."+(n>99?n:"0"+a(n))+"Z"}})},function(e,t,n){var r=Date.prototype,i="Invalid Date",o="toString",a=r[o],s=r.getTime;new Date(NaN)+""!=i&&n(18)(r,o,function(){var e=s.call(this);return e===e?a.call(this):i})},function(e,t,n){var r=n(25)("toPrimitive"),i=Date.prototype;r in i||n(10)(i,r,n(158))},function(e,t,n){"use strict";var r=n(12),i=n(16),o="number";e.exports=function(e){if("string"!==e&&e!==o&&"default"!==e)throw TypeError("Incorrect hint");return i(r(this),e!=o)}},function(e,t,n){var r=n(8);r(r.S,"Array",{isArray:n(45)})},[1413,20,8,58,161,162,37,163,164,165],[1414,12],[1415,129,25],[1416,11,17],[1417,75,25,129,9],[1418,25],function(e,t,n){"use strict";var r=n(8),i=n(163);r(r.S+r.F*n(7)(function(){function e(){}return!(Array.of.call(e)instanceof e)}),"Array",{of:function(){for(var e=0,t=arguments.length,n=new("function"==typeof this?this:Array)(t);t>e;)i(n,e,arguments[e++]);return n.length=t,n}})},function(e,t,n){"use strict";var r=n(8),i=n(32),o=[].join;r(r.P+r.F*(n(33)!=Object||!n(168)(o)),"Array",{join:function(e){return o.call(i(this),void 0===e?",":e)}})},function(e,t,n){var r=n(7);e.exports=function(e,t){return!!e&&r(function(){t?e.call(null,function(){},1):e.call(null)})}},function(e,t,n){"use strict";var r=n(8),i=n(48),o=n(34),a=n(39),s=n(37),u=[].slice;r(r.P+r.F*n(7)(function(){i&&u.call(i)}),"Array",{slice:function(e,t){var n=s(this.length),r=o(this);if(t=void 0===t?n:t,"Array"==r)return u.call(this,e,t);for(var i=a(e,n),c=a(t,n),l=s(c-i),p=Array(l),f=0;f=0:p>f;f+=h)f in l&&(s=t(s,l[f],f,c));return s}},function(e,t,n){"use strict";var r=n(8),i=n(180);r(r.P+r.F*!n(168)([].reduceRight,!0),"Array",{reduceRight:function(e){return i(this,e,arguments.length,arguments[1],!0)}})},function(e,t,n){"use strict";var r=n(8),i=n(36)(!1),o=[].indexOf,a=!!o&&1/[1].indexOf(1,-0)<0;r(r.P+r.F*(a||!n(168)(o)),"Array",{indexOf:function(e){return a?o.apply(this,arguments)||0:i(this,e,arguments[1])}})},function(e,t,n){"use strict";var r=n(8),i=n(32),o=n(38),a=n(37),s=[].lastIndexOf,u=!!s&&1/[1].lastIndexOf(1,-0)<0;r(r.P+r.F*(u||!n(168)(s)),"Array",{lastIndexOf:function(e){if(u)return s.apply(this,arguments)||0;var t=i(this),n=a(t.length),r=n-1;for(arguments.length>1&&(r=Math.min(r,o(arguments[1]))),r<0&&(r=n+r);r>=0;r--)if(r in t&&t[r]===e)return r||0;return-1}})},function(e,t,n){var r=n(8);r(r.P,"Array",{copyWithin:n(185)}),n(186)("copyWithin")},function(e,t,n){"use strict";var r=n(58),i=n(39),o=n(37);e.exports=[].copyWithin||function(e,t){var n=r(this),a=o(n.length),s=i(e,a),u=i(t,a),c=arguments.length>2?arguments[2]:void 0,l=Math.min((void 0===c?a:i(c,a))-u,a-s),p=1;for(u0;)u in n?n[s]=n[u]:delete n[s],s+=p,u+=p;return n}},function(e,t,n){var r=n(25)("unscopables"),i=Array.prototype;void 0==i[r]&&n(10)(i,r,{}),e.exports=function(e){i[r][e]=!0}},function(e,t,n){var r=n(8);r(r.P,"Array",{fill:n(188)}),n(186)("fill")},function(e,t,n){"use strict";var r=n(58),i=n(39),o=n(37);e.exports=function(e){for(var t=r(this),n=o(t.length),a=arguments.length,s=i(a>1?arguments[1]:void 0,n),u=a>2?arguments[2]:void 0,c=void 0===u?n:i(u,n);c>s;)t[s++]=e;return t}},function(e,t,n){"use strict";var r=n(8),i=n(172)(5),o="find",a=!0;o in[]&&Array(1)[o](function(){a=!1}),r(r.P+r.F*a,"Array",{find:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}}),n(186)(o)},function(e,t,n){"use strict";var r=n(8),i=n(172)(6),o="findIndex",a=!0;o in[]&&Array(1)[o](function(){a=!1}),r(r.P+r.F*a,"Array",{findIndex:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}}),n(186)(o)},function(e,t,n){n(192)("Array")},function(e,t,n){"use strict";var r=n(4),i=n(11),o=n(6),a=n(25)("species");e.exports=function(e){var t=r[e];o&&t&&!t[a]&&i.f(t,a,{configurable:!0,get:function(){return this}})}},[1422,186,194,129,32,128],function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,n){var r=n(4),i=n(88),o=n(11).f,a=n(50).f,s=n(134),u=n(196),c=r.RegExp,l=c,p=c.prototype,f=/a/g,h=/a/g,d=new c(f)!==f;if(n(6)&&(!d||n(7)(function(){return h[n(25)("match")]=!1,c(f)!=f||c(h)==h||"/a/i"!=c(f,"i")}))){c=function(e,t){var n=this instanceof c,r=s(e),o=void 0===t;return!n&&r&&e.constructor===c&&o?e:i(d?new l(r&&!o?e.source:e,t):l((r=e instanceof c)?e.source:e,r&&o?u.call(e):t),n?this:p,c)};for(var m=(function(e){e in c||o(c,e,{configurable:!0,get:function(){return l[e]},set:function(t){l[e]=t}})}),y=a(l),v=0;y.length>v;)m(y[v++]);p.constructor=c,c.prototype=p,n(18)(r,"RegExp",c)}n(192)("RegExp")},function(e,t,n){"use strict";var r=n(12);e.exports=function(){var e=r(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t}},function(e,t,n){"use strict";n(198);var r=n(12),i=n(196),o=n(6),a="toString",s=/./[a],u=function(e){n(18)(RegExp.prototype,a,e,!0)};n(7)(function(){return"/a/b"!=s.call({source:"a",flags:"b"})})?u(function(){var e=r(this);return"/".concat(e.source,"/","flags"in e?e.flags:!o&&e instanceof RegExp?i.call(e):void 0)}):s.name!=a&&u(function(){return s.call(this)})},function(e,t,n){n(6)&&"g"!=/./g.flags&&n(11).f(RegExp.prototype,"flags",{configurable:!0,get:n(196)})},function(e,t,n){n(200)("match",1,function(e,t,n){return[function(n){"use strict";var r=e(this),i=void 0==n?void 0:n[t];return void 0!==i?i.call(n,r):new RegExp(n)[t](String(r))},n]})},function(e,t,n){"use strict";var r=n(10),i=n(18),o=n(7),a=n(35),s=n(25);e.exports=function(e,t,n){var u=s(e),c=n(a,u,""[e]),l=c[0],p=c[1];o(function(){var t={};return t[u]=function(){return 7},7!=""[e](t)})&&(i(String.prototype,e,l),r(RegExp.prototype,u,2==t?function(e,t){return p.call(e,this,t)}:function(e){return p.call(e,this)}))}},function(e,t,n){n(200)("replace",2,function(e,t,n){return[function(r,i){"use strict";var o=e(this),a=void 0==r?void 0:r[t];return void 0!==a?a.call(r,o,i):n.call(String(o),r,i)},n]})},function(e,t,n){n(200)("search",1,function(e,t,n){return[function(n){"use strict";var r=e(this),i=void 0==n?void 0:n[t];return void 0!==i?i.call(n,r):new RegExp(n)[t](String(r))},n]})},function(e,t,n){n(200)("split",2,function(e,t,r){"use strict";var i=n(134),o=r,a=[].push,s="split",u="length",c="lastIndex";if("c"=="abbc"[s](/(b)*/)[1]||4!="test"[s](/(?:)/,-1)[u]||2!="ab"[s](/(?:ab)*/)[u]||4!="."[s](/(.?)(.?)/)[u]||"."[s](/()()/)[u]>1||""[s](/.?/)[u]){var l=void 0===/()??/.exec("")[1];r=function(e,t){var n=String(this);if(void 0===e&&0===t)return[];if(!i(e))return o.call(n,e,t);var r,s,p,f,h,d=[],m=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),y=0,v=void 0===t?4294967295:t>>>0,g=new RegExp(e.source,m+"g");for(l||(r=new RegExp("^"+g.source+"$(?!\\s)",m));(s=g.exec(n))&&(p=s.index+s[0][u],!(p>y&&(d.push(n.slice(y,s.index)),!l&&s[u]>1&&s[0].replace(r,function(){for(h=1;h1&&s.index=v)));)g[c]===s.index&&g[c]++;return y===n[u]?!f&&g.test("")||d.push(""):d.push(n.slice(y)),d[u]>v?d.slice(0,v):d}}else"0"[s](void 0,0)[u]&&(r=function(e,t){return void 0===e&&0===t?[]:o.call(this,e,t)});return[function(n,i){var o=e(this),a=void 0==n?void 0:n[t];return void 0!==a?a.call(n,o,i):r.call(String(o),n,i)},r]})},[1423,28,4,20,75,8,13,21,205,206,207,208,209,25,210,24,192,9,165],function(e,t){e.exports=function(e,t,n,r){if(!(e instanceof t)||void 0!==r&&r in e)throw TypeError(n+": incorrect invocation!");return e}},[1424,20,161,162,12,37,164],[1425,12,21,25],[1426,20,78,48,15,4,34],[1427,4,208,34],function(e,t,n){var r=n(18);e.exports=function(e,t,n){for(var i in t)r(e,i,t[i],n);return e}},function(e,t,n){"use strict";var r=n(212);e.exports=n(213)("Map",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{get:function(e){var t=r.getEntry(this,e);return t&&t.v},set:function(e,t){return r.def(this,0===e?0:e,t)}},r,!0)},function(e,t,n){"use strict";var r=n(11).f,i=n(46),o=n(210),a=n(20),s=n(205),u=n(35),c=n(206),l=n(128),p=n(194),f=n(192),h=n(6),d=n(22).fastKey,m=h?"_s":"size",y=function(e,t){var n,r=d(t);if("F"!==r)return e._i[r];for(n=e._f;n;n=n.n)if(n.k==t)return n};e.exports={getConstructor:function(e,t,n,l){var p=e(function(e,r){s(e,p,t,"_i"),e._i=i(null),e._f=void 0,e._l=void 0,e[m]=0,void 0!=r&&c(r,n,e[l],e)});return o(p.prototype,{clear:function(){for(var e=this,t=e._i,n=e._f;n;n=n.n)n.r=!0,n.p&&(n.p=n.p.n=void 0),delete t[n.i];e._f=e._l=void 0,e[m]=0},delete:function(e){var t=this,n=y(t,e);if(n){var r=n.n,i=n.p;delete t._i[n.i],n.r=!0,i&&(i.n=r),r&&(r.p=i),t._f==n&&(t._f=r),t._l==n&&(t._l=i),t[m]--}return!!n},forEach:function(e){s(this,p,"forEach");for(var t,n=a(e,arguments.length>1?arguments[1]:void 0,3);t=t?t.n:this._f;)for(n(t.v,t.k,this);t&&t.r;)t=t.p},has:function(e){return!!y(this,e)}}),h&&r(p.prototype,"size",{get:function(){return u(this[m])}}),p},def:function(e,t,n){var r,i,o=y(e,t);return o?o.v=n:(e._l=o={i:i=d(t,!0),k:t,v:n,p:r=e._l,n:void 0,r:!1},e._f||(e._f=o),
+r&&(r.n=o),e[m]++,"F"!==i&&(e._i[i]=o)),e},getEntry:y,setStrong:function(e,t,n){l(e,t,function(e,t){this._t=e,this._k=t,this._l=void 0},function(){for(var e=this,t=e._k,n=e._l;n&&n.r;)n=n.p;return e._t&&(e._l=n=n?n.n:e._t._f)?"keys"==t?p(0,n.k):"values"==t?p(0,n.v):p(0,[n.k,n.v]):(e._t=void 0,p(1))},n?"entries":"values",!n,!0),f(t)}}},function(e,t,n){"use strict";var r=n(4),i=n(8),o=n(18),a=n(210),s=n(22),u=n(206),c=n(205),l=n(13),p=n(7),f=n(165),h=n(24),d=n(88);e.exports=function(e,t,n,m,y,v){var g=r[e],_=g,b=y?"set":"add",w=_&&_.prototype,x={},k=function(e){var t=w[e];o(w,e,"delete"==e?function(e){return!(v&&!l(e))&&t.call(this,0===e?0:e)}:"has"==e?function(e){return!(v&&!l(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return v&&!l(e)?void 0:t.call(this,0===e?0:e)}:"add"==e?function(e){return t.call(this,0===e?0:e),this}:function(e,n){return t.call(this,0===e?0:e,n),this})};if("function"==typeof _&&(v||w.forEach&&!p(function(){(new _).entries().next()}))){var S=new _,E=S[b](v?{}:-0,1)!=S,C=p(function(){S.has(1)}),A=f(function(e){new _(e)}),T=!v&&p(function(){for(var e=new _,t=5;t--;)e[b](t,t);return!e.has(-0)});A||(_=t(function(t,n){c(t,_,e);var r=d(new g,t,_);return void 0!=n&&u(n,y,r[b],r),r}),_.prototype=w,w.constructor=_),(C||T)&&(k("delete"),k("has"),y&&k("get")),(T||E)&&k(b),v&&w.clear&&delete w.clear}else _=m.getConstructor(t,e,y,b),a(_.prototype,n),s.NEED=!0;return h(_,e),x[e]=_,i(i.G+i.W+i.F*(_!=g),x),v||m.setStrong(_,e,y),_}},function(e,t,n){"use strict";var r=n(212);e.exports=n(213)("Set",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{add:function(e){return r.def(this,e=0===e?0:e,e)}},r)},[1428,172,18,22,69,216,13,213],[1429,210,22,12,13,205,206,172,5],function(e,t,n){"use strict";var r=n(216);n(213)("WeakSet",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{add:function(e){return r.def(this,e,!0)}},r,!1,!0)},function(e,t,n){"use strict";var r=n(8),i=n(219),o=n(220),a=n(12),s=n(39),u=n(37),c=n(13),l=n(4).ArrayBuffer,p=n(207),f=o.ArrayBuffer,h=o.DataView,d=i.ABV&&l.isView,m=f.prototype.slice,y=i.VIEW,v="ArrayBuffer";r(r.G+r.W+r.F*(l!==f),{ArrayBuffer:f}),r(r.S+r.F*!i.CONSTR,v,{isView:function(e){return d&&d(e)||c(e)&&y in e}}),r(r.P+r.U+r.F*n(7)(function(){return!new f(2).slice(1,void 0).byteLength}),v,{slice:function(e,t){if(void 0!==m&&void 0===t)return m.call(a(this),e);for(var n=a(this).byteLength,r=s(e,n),i=s(void 0===t?n:t,n),o=new(p(this,f))(u(i-r)),c=new h(this),l=new h(o),d=0;r>1,l=23===t?O(2,-24)-O(2,-77):0,p=0,f=e<0||0===e&&1/e<0?1:0;for(e=T(e),e!=e||e===C?(i=e!=e?1:0,r=u):(r=D(M(e)/P),e*(o=O(2,-r))<1&&(r--,o*=2),e+=r+c>=1?l/o:l*O(2,1-c),e*o>=2&&(r++,o/=2),r+c>=u?(i=0,r=u):r+c>=1?(i=(e*o-1)*O(2,t),r+=c):(i=e*O(2,c-1)*O(2,t),r=0));t>=8;a[p++]=255&i,i/=256,t-=8);for(r=r<0;a[p++]=255&r,r/=256,s-=8);return a[--p]|=128*f,a},L=function(e,t,n){var r,i=8*n-t-1,o=(1<>1,s=i-7,u=n-1,c=e[u--],l=127&c;for(c>>=7;s>0;l=256*l+e[u],u--,s-=8);for(r=l&(1<<-s)-1,l>>=-s,s+=t;s>0;r=256*r+e[u],u--,s-=8);if(0===l)l=1-a;else{if(l===o)return r?NaN:c?-C:C;r+=O(2,t),l-=a}return(c?-1:1)*r*O(2,l-t)},U=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},q=function(e){return[255&e]},W=function(e){return[255&e,e>>8&255]},K=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},V=function(e){return z(e,52,8)},H=function(e){return z(e,23,4)},J=function(e,t,n){d(e[_],t,{get:function(){return this[n]}})},G=function(e,t,n,r){var i=+n,o=p(i);if(i!=o||o<0||o+t>e[B])throw E(w);var a=e[F]._b,s=o+e[N],u=a.slice(s,s+t);return r?u:u.reverse()},X=function(e,t,n,r,i,o){var a=+n,s=p(a);if(a!=s||s<0||s+t>e[B])throw E(w);for(var u=e[F]._b,c=s+e[N],l=r(+i),f=0;fee;)($=Q[ee++])in x||s(x,$,A[$]);o||(Z.constructor=x)}var te=new k(new x(2)),ne=k[_].setInt8;te.setInt8(0,2147483648),te.setInt8(1,2147483649),!te.getInt8(0)&&te.getInt8(1)||u(k[_],{setInt8:function(e,t){ne.call(this,e,t<<24>>24)},setUint8:function(e,t){ne.call(this,e,t<<24>>24)}},!0)}else x=function(e){var t=Y(this,e);this._b=m.call(Array(t),0),this[B]=t},k=function(e,t,n){l(this,k,g),l(e,x,g);var r=e[B],i=p(t);if(i<0||i>r)throw E("Wrong offset!");if(n=void 0===n?r-i:f(n),i+n>r)throw E(b);this[F]=e,this[N]=i,this[B]=n},i&&(J(x,j,"_l"),J(k,I,"_b"),J(k,j,"_l"),J(k,R,"_o")),u(k[_],{getInt8:function(e){return G(this,1,e)[0]<<24>>24},getUint8:function(e){return G(this,1,e)[0]},getInt16:function(e){var t=G(this,2,e,arguments[1]);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=G(this,2,e,arguments[1]);return t[1]<<8|t[0]},getInt32:function(e){return U(G(this,4,e,arguments[1]))},getUint32:function(e){return U(G(this,4,e,arguments[1]))>>>0},getFloat32:function(e){return L(G(this,4,e,arguments[1]),23,4)},getFloat64:function(e){return L(G(this,8,e,arguments[1]),52,8)},setInt8:function(e,t){X(this,1,e,q,t)},setUint8:function(e,t){X(this,1,e,q,t)},setInt16:function(e,t){X(this,2,e,W,t,arguments[2])},setUint16:function(e,t){X(this,2,e,W,t,arguments[2])},setInt32:function(e,t){X(this,4,e,K,t,arguments[2])},setUint32:function(e,t){X(this,4,e,K,t,arguments[2])},setFloat32:function(e,t){X(this,4,e,H,t,arguments[2])},setFloat64:function(e,t){X(this,8,e,V,t,arguments[2])}});y(x,v),y(k,g),s(k[_],a.VIEW,!0),t[v]=x,t[g]=k},function(e,t,n){var r=n(8);r(r.G+r.W+r.F*!n(219).ABV,{DataView:n(220).DataView})},function(e,t,n){n(223)("Int8",1,function(e){return function(t,n,r){return e(this,t,n,r)}})},function(e,t,n){"use strict";if(n(6)){var r=n(28),i=n(4),o=n(7),a=n(8),s=n(219),u=n(220),c=n(20),l=n(205),p=n(17),f=n(10),h=n(210),d=n(38),m=n(37),y=n(39),v=n(16),g=n(5),_=n(71),b=n(75),w=n(13),x=n(58),k=n(162),S=n(46),E=n(59),C=n(50).f,A=n(164),T=n(19),O=n(25),D=n(172),M=n(36),P=n(207),I=n(193),j=n(129),R=n(165),F=n(192),B=n(188),N=n(185),z=n(11),L=n(51),U=z.f,q=L.f,W=i.RangeError,K=i.TypeError,V=i.Uint8Array,H="ArrayBuffer",J="Shared"+H,G="BYTES_PER_ELEMENT",X="prototype",Y=Array[X],$=u.ArrayBuffer,Z=u.DataView,Q=D(0),ee=D(2),te=D(3),ne=D(4),re=D(5),ie=D(6),oe=M(!0),ae=M(!1),se=I.values,ue=I.keys,ce=I.entries,le=Y.lastIndexOf,pe=Y.reduce,fe=Y.reduceRight,he=Y.join,de=Y.sort,me=Y.slice,ye=Y.toString,ve=Y.toLocaleString,ge=O("iterator"),_e=O("toStringTag"),be=T("typed_constructor"),we=T("def_constructor"),xe=s.CONSTR,ke=s.TYPED,Se=s.VIEW,Ee="Wrong length!",Ce=D(1,function(e,t){return Pe(P(e,e[we]),t)}),Ae=o(function(){return 1===new V(new Uint16Array([1]).buffer)[0]}),Te=!!V&&!!V[X].set&&o(function(){new V(1).set({})}),Oe=function(e,t){if(void 0===e)throw K(Ee);var n=+e,r=m(e);if(t&&!_(n,r))throw W(Ee);return r},De=function(e,t){var n=d(e);if(n<0||n%t)throw W("Wrong offset!");return n},Me=function(e){if(w(e)&&ke in e)return e;throw K(e+" is not a typed array!")},Pe=function(e,t){if(!(w(e)&&be in e))throw K("It is not a typed array constructor!");return new e(t)},Ie=function(e,t){return je(P(e,e[we]),t)},je=function(e,t){for(var n=0,r=t.length,i=Pe(e,r);r>n;)i[n]=t[n++];return i},Re=function(e,t,n){U(e,t,{get:function(){return this._d[n]}})},Fe=function(e){var t,n,r,i,o,a,s=x(e),u=arguments.length,l=u>1?arguments[1]:void 0,p=void 0!==l,f=A(s);if(void 0!=f&&!k(f)){for(a=f.call(s),r=[],t=0;!(o=a.next()).done;t++)r.push(o.value);s=r}for(p&&u>2&&(l=c(l,arguments[2],2)),t=0,n=m(s.length),i=Pe(this,n);n>t;t++)i[t]=p?l(s[t],t):s[t];return i},Be=function(){for(var e=0,t=arguments.length,n=Pe(this,t);t>e;)n[e]=arguments[e++];return n},Ne=!!V&&o(function(){ve.call(new V(1))}),ze=function(){return ve.apply(Ne?me.call(Me(this)):Me(this),arguments)},Le={copyWithin:function(e,t){return N.call(Me(this),e,t,arguments.length>2?arguments[2]:void 0)},every:function(e){return ne(Me(this),e,arguments.length>1?arguments[1]:void 0)},fill:function(e){return B.apply(Me(this),arguments)},filter:function(e){return Ie(this,ee(Me(this),e,arguments.length>1?arguments[1]:void 0))},find:function(e){return re(Me(this),e,arguments.length>1?arguments[1]:void 0)},findIndex:function(e){return ie(Me(this),e,arguments.length>1?arguments[1]:void 0)},forEach:function(e){Q(Me(this),e,arguments.length>1?arguments[1]:void 0)},indexOf:function(e){return ae(Me(this),e,arguments.length>1?arguments[1]:void 0)},includes:function(e){return oe(Me(this),e,arguments.length>1?arguments[1]:void 0)},join:function(e){return he.apply(Me(this),arguments)},lastIndexOf:function(e){return le.apply(Me(this),arguments)},map:function(e){return Ce(Me(this),e,arguments.length>1?arguments[1]:void 0)},reduce:function(e){return pe.apply(Me(this),arguments)},reduceRight:function(e){return fe.apply(Me(this),arguments)},reverse:function(){for(var e,t=this,n=Me(t).length,r=Math.floor(n/2),i=0;i1?arguments[1]:void 0)},sort:function(e){return de.call(Me(this),e)},subarray:function(e,t){var n=Me(this),r=n.length,i=y(e,r);return new(P(n,n[we]))(n.buffer,n.byteOffset+i*n.BYTES_PER_ELEMENT,m((void 0===t?r:y(t,r))-i))}},Ue=function(e,t){return Ie(this,me.call(Me(this),e,t))},qe=function(e){Me(this);var t=De(arguments[1],1),n=this.length,r=x(e),i=m(r.length),o=0;if(i+t>n)throw W(Ee);for(;o255?255:255&r),i.v[d](n*t+i.o,r,Ae)},O=function(e,t){U(e,t,{get:function(){return A(this,t)},set:function(e){return T(this,t,e)},enumerable:!0})};_?(y=n(function(e,n,r,i){l(e,y,c,"_d");var o,a,s,u,p=0,h=0;if(w(n)){if(!(n instanceof $||(u=b(n))==H||u==J))return ke in n?je(y,n):Fe.call(y,n);o=n,h=De(r,t);var d=n.byteLength;if(void 0===i){if(d%t)throw W(Ee);if(a=d-h,a<0)throw W(Ee)}else if(a=m(i)*t,a+h>d)throw W(Ee);s=a/t}else s=Oe(n,!0),a=s*t,o=new $(a);for(f(e,"_d",{b:o,o:h,l:a,e:s,v:new Z(o)});p=n.length)return{value:void 0,done:!0};while(!((e=n[t._i++])in t._t));return{value:e,done:!1}}),r(r.S,"Reflect",{enumerate:function(e){return new o(e)}})},function(e,t,n){function r(e,t){var n,s,l=arguments.length<3?e:arguments[2];return c(e)===l?e[t]:(n=i.f(e,t))?a(n,"value")?n.value:void 0!==n.get?n.get.call(l):void 0:u(s=o(e))?r(s,t,l):void 0}var i=n(51),o=n(59),a=n(5),s=n(8),u=n(13),c=n(12);s(s.S,"Reflect",{get:r})},function(e,t,n){var r=n(51),i=n(8),o=n(12);i(i.S,"Reflect",{getOwnPropertyDescriptor:function(e,t){return r.f(o(e),t)}})},function(e,t,n){var r=n(8),i=n(59),o=n(12);r(r.S,"Reflect",{getPrototypeOf:function(e){return i(o(e))}})},function(e,t,n){var r=n(8);r(r.S,"Reflect",{has:function(e,t){return t in e}})},function(e,t,n){var r=n(8),i=n(12),o=Object.isExtensible;r(r.S,"Reflect",{isExtensible:function(e){return i(e),!o||o(e)}})},function(e,t,n){var r=n(8);r(r.S,"Reflect",{ownKeys:n(243)})},function(e,t,n){var r=n(50),i=n(43),o=n(12),a=n(4).Reflect;e.exports=a&&a.ownKeys||function(e){var t=r.f(o(e)),n=i.f;return n?t.concat(n(e)):t}},function(e,t,n){var r=n(8),i=n(12),o=Object.preventExtensions;r(r.S,"Reflect",{preventExtensions:function(e){i(e);try{return o&&o(e),!0}catch(e){return!1}}})},function(e,t,n){function r(e,t,n){var u,f,h=arguments.length<4?e:arguments[3],d=o.f(l(e),t);if(!d){if(p(f=a(e)))return r(f,t,n,h);d=c(0)}return s(d,"value")?!(d.writable===!1||!p(h))&&(u=o.f(h,t)||c(0),u.value=n,i.f(h,t,u),!0):void 0!==d.set&&(d.set.call(h,n),!0)}var i=n(11),o=n(51),a=n(59),s=n(5),u=n(8),c=n(17),l=n(12),p=n(13);u(u.S,"Reflect",{set:r})},function(e,t,n){var r=n(8),i=n(73);i&&r(r.S,"Reflect",{setPrototypeOf:function(e,t){i.check(e,t);try{return i.set(e,t),!0}catch(e){return!1}}})},function(e,t,n){"use strict";var r=n(8),i=n(36)(!0);r(r.P,"Array",{includes:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}}),n(186)("includes")},function(e,t,n){"use strict";var r=n(8),i=n(127)(!0);r(r.P,"String",{at:function(e){return i(this,e)}})},function(e,t,n){"use strict";var r=n(8),i=n(250);r(r.P,"String",{padStart:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0,!0)}})},function(e,t,n){var r=n(37),i=n(91),o=n(35);e.exports=function(e,t,n,a){var s=String(o(e)),u=s.length,c=void 0===n?" ":String(n),l=r(t);if(l<=u||""==c)return s;var p=l-u,f=i.call(c,Math.ceil(p/c.length));return f.length>p&&(f=f.slice(0,p)),a?f+s:s+f}},function(e,t,n){"use strict";var r=n(8),i=n(250);r(r.P,"String",{padEnd:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0,!1)}})},function(e,t,n){"use strict";n(83)("trimLeft",function(e){return function(){return e(this,1)}},"trimStart")},function(e,t,n){"use strict";n(83)("trimRight",function(e){return function(){return e(this,2)}},"trimEnd")},function(e,t,n){"use strict";var r=n(8),i=n(35),o=n(37),a=n(134),s=n(196),u=RegExp.prototype,c=function(e,t){this._r=e,this._s=t};n(130)(c,"RegExp String",function(){var e=this._r.exec(this._s);return{value:e,done:null===e}}),r(r.P,"String",{matchAll:function(e){if(i(this),!a(e))throw TypeError(e+" is not a regexp!");var t=String(this),n="flags"in u?String(e.flags):s.call(e),r=new RegExp(e.source,~n.indexOf("g")?n:"g"+n);return r.lastIndex=o(e.lastIndex),new c(r,t)}})},[1430,27],[1431,27],function(e,t,n){var r=n(8),i=n(243),o=n(32),a=n(51),s=n(163);r(r.S,"Object",{getOwnPropertyDescriptors:function(e){for(var t,n=o(e),r=a.f,u=i(n),c={},l=0;u.length>l;)s(c,t=u[l++],r(n,t));return c}})},function(e,t,n){var r=n(8),i=n(259)(!1);r(r.S,"Object",{values:function(e){return i(e)}})},function(e,t,n){var r=n(30),i=n(32),o=n(44).f;e.exports=function(e){return function(t){for(var n,a=i(t),s=r(a),u=s.length,c=0,l=[];u>c;)o.call(a,n=s[c++])&&l.push(e?[n,a[n]]:a[n]);return l}}},function(e,t,n){var r=n(8),i=n(259)(!0);r(r.S,"Object",{entries:function(e){return i(e)}})},function(e,t,n){"use strict";var r=n(8),i=n(58),o=n(21),a=n(11);n(6)&&r(r.P+n(262),"Object",{__defineGetter__:function(e,t){a.f(i(this),e,{get:o(t),enumerable:!0,configurable:!0})}})},function(e,t,n){e.exports=n(28)||!n(7)(function(){var e=Math.random();__defineSetter__.call(null,e,function(){}),delete n(4)[e]})},function(e,t,n){"use strict";var r=n(8),i=n(58),o=n(21),a=n(11);n(6)&&r(r.P+n(262),"Object",{__defineSetter__:function(e,t){a.f(i(this),e,{set:o(t),enumerable:!0,configurable:!0})}})},function(e,t,n){"use strict";var r=n(8),i=n(58),o=n(16),a=n(59),s=n(51).f;n(6)&&r(r.P+n(262),"Object",{__lookupGetter__:function(e){var t,n=i(this),r=o(e,!0);do if(t=s(n,r))return t.get;while(n=a(n))}})},function(e,t,n){"use strict";var r=n(8),i=n(58),o=n(16),a=n(59),s=n(51).f;n(6)&&r(r.P+n(262),"Object",{__lookupSetter__:function(e){var t,n=i(this),r=o(e,!0);do if(t=s(n,r))return t.set;while(n=a(n))}})},function(e,t,n){var r=n(8);r(r.P+r.R,"Map",{toJSON:n(267)("Map")})},function(e,t,n){var r=n(75),i=n(268);e.exports=function(e){return function(){if(r(this)!=e)throw TypeError(e+"#toJSON isn't generic");return i(this)}}},function(e,t,n){var r=n(206);e.exports=function(e,t){var n=[];return r(e,!1,n.push,n,t),n}},function(e,t,n){var r=n(8);r(r.P+r.R,"Set",{toJSON:n(267)("Set")})},function(e,t,n){var r=n(8);r(r.S,"System",{global:n(4)})},function(e,t,n){var r=n(8),i=n(34);r(r.S,"Error",{isError:function(e){return"Error"===i(e)}})},function(e,t,n){var r=n(8);r(r.S,"Math",{iaddh:function(e,t,n,r){var i=e>>>0,o=t>>>0,a=n>>>0;return o+(r>>>0)+((i&a|(i|a)&~(i+a>>>0))>>>31)|0}})},function(e,t,n){var r=n(8);r(r.S,"Math",{isubh:function(e,t,n,r){var i=e>>>0,o=t>>>0,a=n>>>0;return o-(r>>>0)-((~i&a|~(i^a)&i-a>>>0)>>>31)|0}})},function(e,t,n){var r=n(8);r(r.S,"Math",{imulh:function(e,t){var n=65535,r=+e,i=+t,o=r&n,a=i&n,s=r>>16,u=i>>16,c=(s*a>>>0)+(o*a>>>16);return s*u+(c>>16)+((o*u>>>0)+(c&n)>>16)}})},function(e,t,n){var r=n(8);r(r.S,"Math",{umulh:function(e,t){var n=65535,r=+e,i=+t,o=r&n,a=i&n,s=r>>>16,u=i>>>16,c=(s*a>>>0)+(o*a>>>16);return s*u+(c>>>16)+((o*u>>>0)+(c&n)>>>16)}})},function(e,t,n){var r=n(277),i=n(12),o=r.key,a=r.set;r.exp({defineMetadata:function(e,t,n,r){a(e,t,i(n),o(r))}})},function(e,t,n){var r=n(211),i=n(8),o=n(23)("metadata"),a=o.store||(o.store=new(n(215))),s=function(e,t,n){var i=a.get(e);if(!i){if(!n)return;a.set(e,i=new r)}var o=i.get(t);if(!o){if(!n)return;i.set(t,o=new r)}return o},u=function(e,t,n){var r=s(t,n,!1);return void 0!==r&&r.has(e)},c=function(e,t,n){var r=s(t,n,!1);return void 0===r?void 0:r.get(e)},l=function(e,t,n,r){s(n,r,!0).set(e,t)},p=function(e,t){var n=s(e,t,!1),r=[];return n&&n.forEach(function(e,t){r.push(t)}),r},f=function(e){return void 0===e||"symbol"==typeof e?e:String(e)},h=function(e){i(i.S,"Reflect",e)};e.exports={store:a,map:s,has:u,get:c,set:l,keys:p,key:f,exp:h}},function(e,t,n){var r=n(277),i=n(12),o=r.key,a=r.map,s=r.store;r.exp({deleteMetadata:function(e,t){var n=arguments.length<3?void 0:o(arguments[2]),r=a(i(t),n,!1);if(void 0===r||!r.delete(e))return!1;if(r.size)return!0;var u=s.get(t);return u.delete(n),!!u.size||s.delete(t)}})},function(e,t,n){var r=n(277),i=n(12),o=n(59),a=r.has,s=r.get,u=r.key,c=function(e,t,n){var r=a(e,t,n);if(r)return s(e,t,n);var i=o(t);return null!==i?c(e,i,n):void 0};r.exp({getMetadata:function(e,t){return c(e,i(t),arguments.length<3?void 0:u(arguments[2]))}})},function(e,t,n){var r=n(214),i=n(268),o=n(277),a=n(12),s=n(59),u=o.keys,c=o.key,l=function(e,t){var n=u(e,t),o=s(e);if(null===o)return n;var a=l(o,t);return a.length?n.length?i(new r(n.concat(a))):a:n};o.exp({getMetadataKeys:function(e){return l(a(e),arguments.length<2?void 0:c(arguments[1]))}})},function(e,t,n){var r=n(277),i=n(12),o=r.get,a=r.key;r.exp({getOwnMetadata:function(e,t){return o(e,i(t),arguments.length<3?void 0:a(arguments[2]))}})},function(e,t,n){var r=n(277),i=n(12),o=r.keys,a=r.key;r.exp({getOwnMetadataKeys:function(e){return o(i(e),arguments.length<2?void 0:a(arguments[1]))}})},function(e,t,n){var r=n(277),i=n(12),o=n(59),a=r.has,s=r.key,u=function(e,t,n){var r=a(e,t,n);if(r)return!0;var i=o(t);return null!==i&&u(e,i,n)};r.exp({hasMetadata:function(e,t){return u(e,i(t),arguments.length<3?void 0:s(arguments[2]))}})},function(e,t,n){var r=n(277),i=n(12),o=r.has,a=r.key;r.exp({hasOwnMetadata:function(e,t){return o(e,i(t),arguments.length<3?void 0:a(arguments[2]))}})},function(e,t,n){var r=n(277),i=n(12),o=n(21),a=r.key,s=r.set;r.exp({metadata:function(e,t){return function(n,r){s(e,t,(void 0!==r?i:o)(n),a(r))}}})},function(e,t,n){var r=n(8),i=n(209)(),o=n(4).process,a="process"==n(34)(o);r(r.G,{asap:function(e){var t=a&&o.domain;i(t?t.bind(e):e)}})},function(e,t,n){"use strict";var r=n(8),i=n(4),o=n(9),a=n(209)(),s=n(25)("observable"),u=n(21),c=n(12),l=n(205),p=n(210),f=n(10),h=n(206),d=h.RETURN,m=function(e){return null==e?void 0:u(e)},y=function(e){var t=e._c;t&&(e._c=void 0,t())},v=function(e){return void 0===e._o},g=function(e){v(e)||(e._o=void 0,y(e))},_=function(e,t){c(e),this._c=void 0,this._o=e,e=new b(this);try{var n=t(e),r=n;null!=n&&("function"==typeof n.unsubscribe?n=function(){r.unsubscribe()}:u(n),this._c=n)}catch(t){return void e.error(t)}v(this)&&y(this)};_.prototype=p({},{unsubscribe:function(){g(this)}});var b=function(e){this._s=e};b.prototype=p({},{next:function(e){var t=this._s;if(!v(t)){var n=t._o;try{var r=m(n.next);if(r)return r.call(n,e)}catch(e){try{g(t)}finally{throw e}}}},error:function(e){var t=this._s;if(v(t))throw e;var n=t._o;t._o=void 0;try{var r=m(n.error);if(!r)throw e;e=r.call(n,e)}catch(e){try{y(t)}finally{throw e}}return y(t),e},complete:function(e){var t=this._s;if(!v(t)){var n=t._o;t._o=void 0;try{var r=m(n.complete);e=r?r.call(n,e):void 0}catch(e){try{y(t)}finally{throw e}}return y(t),e}}});var w=function(e){l(this,w,"Observable","_f")._f=u(e)};p(w.prototype,{subscribe:function(e){return new _(e,this._f)},forEach:function(e){var t=this;return new(o.Promise||i.Promise)(function(n,r){u(e);var i=t.subscribe({next:function(t){try{return e(t)}catch(e){r(e),i.unsubscribe()}},error:r,complete:n})})}}),p(w,{from:function(e){var t="function"==typeof this?this:w,n=m(c(e)[s]);if(n){var r=c(n.call(e));return r.constructor===t?r:new t(function(e){return r.subscribe(e)})}return new t(function(t){var n=!1;return a(function(){if(!n){try{if(h(e,!1,function(e){if(t.next(e),n)return d})===d)return}catch(e){if(n)throw e;return void t.error(e)}t.complete()}}),function(){n=!0}})},of:function(){for(var e=0,t=arguments.length,n=Array(t);ea;)(n[a]=arguments[a++])===s&&(u=!0);return function(){var r,o=this,a=arguments.length,c=0,l=0;if(!u&&!a)return i(e,n,o);if(r=n.slice(),u)for(;t>c;c++)r[c]===s&&(r[c]=arguments[l++]);for(;a>l;)r.push(arguments[l++]);return i(e,r,o)}}},function(e,t,n){e.exports=n(4)},function(e,t,n){var r=n(8),i=n(208);r(r.G+r.B,{setImmediate:i.set,clearImmediate:i.clear})},function(e,t,n){for(var r=n(193),i=n(18),o=n(4),a=n(10),s=n(129),u=n(25),c=u("iterator"),l=u("toStringTag"),p=s.Array,f=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],h=0;h<5;h++){var d,m=f[h],y=o[m],v=y&&y.prototype;if(v){v[c]||a(v,c,p),v[l]||a(v,l,m),s[m]=p;for(d in r)v[d]||i(v,d,r[d],!0)}}},function(e,t,n){(function(t,n){!function(t){"use strict";function r(e,t,n,r){var i=t&&t.prototype instanceof o?t:o,a=Object.create(i.prototype),s=new d(r||[]);return a._invoke=l(e,n,s),a}function i(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(e){return{type:"throw",arg:e}}}function o(){}function a(){}function s(){}function u(e){["next","throw","return"].forEach(function(t){e[t]=function(e){return this._invoke(t,e)}})}function c(e){function t(n,r,o,a){var s=i(e[n],e,r);if("throw"!==s.type){var u=s.arg,c=u.value;return c&&"object"==typeof c&&_.call(c,"__await")?Promise.resolve(c.__await).then(function(e){t("next",e,o,a)},function(e){t("throw",e,o,a)}):Promise.resolve(c).then(function(e){u.value=e,o(u)},a)}a(s.arg)}function r(e,n){function r(){return new Promise(function(r,i){t(e,n,r,i)})}return o=o?o.then(r,r):r()}"object"==typeof n&&n.domain&&(t=n.domain.bind(t));var o;this._invoke=r}function l(e,t,n){var r=E;return function(o,a){if(r===A)throw new Error("Generator is already running");if(r===T){if("throw"===o)throw a;return y()}for(n.method=o,n.arg=a;;){var s=n.delegate;if(s){var u=p(s,n);if(u){if(u===O)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(r===E)throw r=T,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r=A;var c=i(e,t,n);if("normal"===c.type){if(r=n.done?T:C,c.arg===O)continue;return{value:c.arg,done:n.done}}"throw"===c.type&&(r=T,n.method="throw",n.arg=c.arg)}}}function p(e,t){var n=e.iterator[t.method];if(n===v){if(t.delegate=null,"throw"===t.method){if(e.iterator.return&&(t.method="return",t.arg=v,p(e,t),"throw"===t.method))return O;t.method="throw",t.arg=new TypeError("The iterator does not provide a 'throw' method")}return O}var r=i(n,e.iterator,t.arg);if("throw"===r.type)return t.method="throw",t.arg=r.arg,t.delegate=null,O;var o=r.arg;return o?o.done?(t[e.resultName]=o.value,t.next=e.nextLoc,"return"!==t.method&&(t.method="next",t.arg=v),t.delegate=null,O):o:(t.method="throw",t.arg=new TypeError("iterator result is not an object"),t.delegate=null,O)}function f(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function h(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function d(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(f,this),this.reset(!0)}function m(e){if(e){var t=e[w];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var n=-1,r=function t(){for(;++n=0;--r){var i=this.tryEntries[r],o=i.completion;if("root"===i.tryLoc)return t("end");if(i.tryLoc<=this.prev){var a=_.call(i,"catchLoc"),s=_.call(i,"finallyLoc");if(a&&s){if(this.prev=0;--n){
+var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&_.call(r,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),h(n),O}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var i=r.arg;h(n)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:m(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=v),O}}}("object"==typeof t?t:"object"==typeof window?window:"object"==typeof self?self:this)}).call(t,function(){return this}(),n(294))},function(e,t){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function i(e){if(l===setTimeout)return setTimeout(e,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(e,0);try{return l(e,0)}catch(t){try{return l.call(null,e,0)}catch(t){return l.call(this,e,0)}}}function o(e){if(p===clearTimeout)return clearTimeout(e);if((p===r||!p)&&clearTimeout)return p=clearTimeout,clearTimeout(e);try{return p(e)}catch(t){try{return p.call(null,e)}catch(t){return p.call(this,e)}}}function a(){m&&h&&(m=!1,h.length?d=h.concat(d):y=-1,d.length&&s())}function s(){if(!m){var e=i(a);m=!0;for(var t=d.length;t;){for(h=d,d=[];++y1)for(var n=1;n
+ * @license MIT
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2015 Viacheslav Lotsmanov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+"use strict";function n(e){return e instanceof t||e instanceof Date||e instanceof RegExp}function r(e){if(e instanceof t){var n=new t(e.length);return e.copy(n),n}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return new RegExp(e);throw new Error("Unexpected situation")}function i(e){var t=[];return e.forEach(function(e,a){"object"==typeof e&&null!==e?Array.isArray(e)?t[a]=i(e):n(e)?t[a]=r(e):t[a]=o({},e):t[a]=e}),t}var o=e.exports=function(){if(arguments.length<1||"object"!=typeof arguments[0])return!1;if(arguments.length<2)return arguments[0];var e,t,a=arguments[0],s=Array.prototype.slice.call(arguments,1);return s.forEach(function(s){"object"!=typeof s||Array.isArray(s)||Object.keys(s).forEach(function(u){return t=a[u],e=s[u],e===a?void 0:"object"!=typeof e||null===e?void(a[u]=e):Array.isArray(e)?void(a[u]=i(e)):n(e)?void(a[u]=r(e)):"object"!=typeof t||null===t||Array.isArray(t)?void(a[u]=o({},e)):void(a[u]=o(t,e))})}),a}}).call(t,n(300).Buffer)},function(e,t,n){(function(e){/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh
+ * @license MIT
+ */
+"use strict";function r(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}function i(){return a.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function o(e,t){if(i()=i())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i().toString(16)+" bytes");return 0|e}function y(e){return+e!=e&&(e=0),a.alloc(+e)}function v(e,t){if(a.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return V(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return G(e).length;default:if(r)return V(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if(n>>>=0,t>>>=0,n<=t)return"";for(e||(e="utf8");;)switch(e){case"hex":return I(this,t,n);case"utf8":case"utf-8":return O(this,t,n);case"ascii":return M(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return j(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function _(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function b(e,t,n,r,i){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=i?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(i)return-1;n=e.length-1}else if(n<0){if(!i)return-1;n=0}if("string"==typeof t&&(t=a.from(t,r)),a.isBuffer(t))return 0===t.length?-1:w(e,t,n,r,i);if("number"==typeof t)return t&=255,a.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):w(e,[t],n,r,i);throw new TypeError("val must be string, number or Buffer")}function w(e,t,n,r,i){function o(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}var a=1,s=e.length,u=t.length;if(void 0!==r&&(r=String(r).toLowerCase(),"ucs2"===r||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,u/=2,n/=2}var c;if(i){var l=-1;for(c=n;cs&&(n=s-u),c=n;c>=0;c--){for(var p=!0,f=0;fi&&(r=i)):r=i;var o=t.length;if(o%2!==0)throw new TypeError("Invalid hex string");r>o/2&&(r=o/2);for(var a=0;a239?4:o>223?3:o>191?2:1;if(i+s<=n){var u,c,l,p;switch(s){case 1:o<128&&(a=o);break;case 2:u=e[i+1],128===(192&u)&&(p=(31&o)<<6|63&u,p>127&&(a=p));break;case 3:u=e[i+1],c=e[i+2],128===(192&u)&&128===(192&c)&&(p=(15&o)<<12|(63&u)<<6|63&c,p>2047&&(p<55296||p>57343)&&(a=p));break;case 4:u=e[i+1],c=e[i+2],l=e[i+3],128===(192&u)&&128===(192&c)&&128===(192&l)&&(p=(15&o)<<18|(63&u)<<12|(63&c)<<6|63&l,p>65535&&p<1114112&&(a=p))}}null===a?(a=65533,s=1):a>65535&&(a-=65536,r.push(a>>>10&1023|55296),a=56320|1023&a),r.push(a),i+=s}return D(r)}function D(e){var t=e.length;if(t<=ee)return String.fromCharCode.apply(String,e);for(var n="",r=0;rr)&&(n=r);for(var i="",o=t;on)throw new RangeError("Trying to access beyond buffer length")}function F(e,t,n,r,i,o){if(!a.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>i||te.length)throw new RangeError("Index out of range")}function B(e,t,n,r){t<0&&(t=65535+t+1);for(var i=0,o=Math.min(e.length-n,2);i>>8*(r?i:1-i)}function N(e,t,n,r){t<0&&(t=4294967295+t+1);for(var i=0,o=Math.min(e.length-n,4);i>>8*(r?i:3-i)&255}function z(e,t,n,r,i,o){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function L(e,t,n,r,i){return i||z(e,t,n,4,3.4028234663852886e38,-3.4028234663852886e38),Z.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||z(e,t,n,8,1.7976931348623157e308,-1.7976931348623157e308),Z.write(e,t,n,r,52,8),n+8}function q(e){if(e=W(e).replace(te,""),e.length<2)return"";for(;e.length%4!==0;)e+="=";return e}function W(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function K(e){return e<16?"0"+e.toString(16):e.toString(16)}function V(e,t){t=t||1/0;for(var n,r=e.length,i=null,o=[],a=0;a55295&&n<57344){if(!i){if(n>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&o.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&o.push(239,191,189),i=n;continue}n=(i-55296<<10|n-56320)+65536}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;o.push(n)}else if(n<2048){if((t-=2)<0)break;o.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function H(e){for(var t=[],n=0;n>8,i=n%256,o.push(i),o.push(r);return o}function G(e){return $.toByteArray(q(e))}function X(e,t,n,r){for(var i=0;i=t.length||i>=e.length);++i)t[i+n]=e[i];return i}function Y(e){return e!==e}var $=n(301),Z=n(302),Q=n(303);t.Buffer=a,t.SlowBuffer=y,t.INSPECT_MAX_BYTES=50,a.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:r(),t.kMaxLength=i(),a.poolSize=8192,a._augment=function(e){return e.__proto__=a.prototype,e},a.from=function(e,t,n){return s(null,e,t,n)},a.TYPED_ARRAY_SUPPORT&&(a.prototype.__proto__=Uint8Array.prototype,a.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&a[Symbol.species]===a&&Object.defineProperty(a,Symbol.species,{value:null,configurable:!0})),a.alloc=function(e,t,n){return c(null,e,t,n)},a.allocUnsafe=function(e){return l(null,e)},a.allocUnsafeSlow=function(e){return l(null,e)},a.isBuffer=function(e){return!(null==e||!e._isBuffer)},a.compare=function(e,t){if(!a.isBuffer(e)||!a.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,i=0,o=Math.min(n,r);i0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},a.prototype.compare=function(e,t,n,r,i){if(!a.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===i&&(i=this.length),t<0||n>e.length||r<0||i>this.length)throw new RangeError("out of range index");if(r>=i&&t>=n)return 0;if(r>=i)return-1;if(t>=n)return 1;if(t>>>=0,n>>>=0,r>>>=0,i>>>=0,this===e)return 0;for(var o=i-r,s=n-t,u=Math.min(o,s),c=this.slice(r,i),l=e.slice(t,n),p=0;pi)&&(n=i),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var o=!1;;)switch(r){case"hex":return x(this,e,t,n);case"utf8":case"utf-8":return k(this,e,t,n);case"ascii":return S(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return C(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return A(this,e,t,n);default:if(o)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),o=!0}},a.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var ee=4096;a.prototype.slice=function(e,t){var n=this.length;e=~~e,t=void 0===t?n:~~t,e<0?(e+=n,e<0&&(e=0)):e>n&&(e=n),t<0?(t+=n,t<0&&(t=0)):t>n&&(t=n),t0&&(i*=256);)r+=this[e+--t]*i;return r},a.prototype.readUInt8=function(e,t){return t||R(e,1,this.length),this[e]},a.prototype.readUInt16LE=function(e,t){return t||R(e,2,this.length),this[e]|this[e+1]<<8},a.prototype.readUInt16BE=function(e,t){return t||R(e,2,this.length),this[e]<<8|this[e+1]},a.prototype.readUInt32LE=function(e,t){return t||R(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},a.prototype.readUInt32BE=function(e,t){return t||R(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},a.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||R(e,t,this.length);for(var r=this[e],i=1,o=0;++o=i&&(r-=Math.pow(2,8*t)),r},a.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||R(e,t,this.length);for(var r=t,i=1,o=this[e+--r];r>0&&(i*=256);)o+=this[e+--r]*i;return i*=128,o>=i&&(o-=Math.pow(2,8*t)),o},a.prototype.readInt8=function(e,t){return t||R(e,1,this.length),128&this[e]?(255-this[e]+1)*-1:this[e]},a.prototype.readInt16LE=function(e,t){t||R(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},a.prototype.readInt16BE=function(e,t){t||R(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},a.prototype.readInt32LE=function(e,t){return t||R(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},a.prototype.readInt32BE=function(e,t){return t||R(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},a.prototype.readFloatLE=function(e,t){return t||R(e,4,this.length),Z.read(this,e,!0,23,4)},a.prototype.readFloatBE=function(e,t){return t||R(e,4,this.length),Z.read(this,e,!1,23,4)},a.prototype.readDoubleLE=function(e,t){return t||R(e,8,this.length),Z.read(this,e,!0,52,8)},a.prototype.readDoubleBE=function(e,t){return t||R(e,8,this.length),Z.read(this,e,!1,52,8)},a.prototype.writeUIntLE=function(e,t,n,r){if(e=+e,t|=0,n|=0,!r){var i=Math.pow(2,8*n)-1;F(this,e,t,n,i,0)}var o=1,a=0;for(this[t]=255&e;++a=0&&(a*=256);)this[t+o]=e/a&255;return t+n},a.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,1,255,0),a.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},a.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):B(this,e,t,!0),t+2},a.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):B(this,e,t,!1),t+2},a.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):N(this,e,t,!0),t+4},a.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},a.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);F(this,e,t,n,i-1,-i)}var o=0,a=1,s=0;for(this[t]=255&e;++o>0)-s&255;return t+n},a.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);F(this,e,t,n,i-1,-i)}var o=n-1,a=1,s=0;for(this[t+o]=255&e;--o>=0&&(a*=256);)e<0&&0===s&&0!==this[t+o+1]&&(s=1),this[t+o]=(e/a>>0)-s&255;return t+n},a.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,1,127,-128),a.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},a.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):B(this,e,t,!0),t+2},a.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):B(this,e,t,!1),t+2},a.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,4,2147483647,-2147483648),a.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):N(this,e,t,!0),t+4},a.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||F(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),a.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},a.prototype.writeFloatLE=function(e,t,n){return L(this,e,t,!0,n)},a.prototype.writeFloatBE=function(e,t,n){return L(this,e,t,!1,n)},a.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},a.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},a.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--i)e[i+t]=this[i+n];else if(o<1e3||!a.TYPED_ARRAY_SUPPORT)for(i=0;i>>=0,n=void 0===n?this.length:n>>>0,e||(e=0);var o;if("number"==typeof e)for(o=t;o0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===e[t-2]?2:"="===e[t-1]?1:0}function r(e){return 3*e.length/4-n(e)}function i(e){var t,r,i,o,a,s,u=e.length;a=n(e),s=new l(3*u/4-a),i=a>0?u-4:u;var p=0;for(t=0,r=0;t>16&255,s[p++]=o>>8&255,s[p++]=255&o;return 2===a?(o=c[e.charCodeAt(t)]<<2|c[e.charCodeAt(t+1)]>>4,s[p++]=255&o):1===a&&(o=c[e.charCodeAt(t)]<<10|c[e.charCodeAt(t+1)]<<4|c[e.charCodeAt(t+2)]>>2,s[p++]=o>>8&255,s[p++]=255&o),s}function o(e){return u[e>>18&63]+u[e>>12&63]+u[e>>6&63]+u[63&e]}function a(e,t,n){for(var r,i=[],a=t;al?l:c+s));return 1===r?(t=e[n-1],i+=u[t>>2],i+=u[t<<4&63],i+="=="):2===r&&(t=(e[n-2]<<8)+e[n-1],i+=u[t>>10],i+=u[t>>4&63],i+=u[t<<2&63],i+="="),o.push(i),o.join("")}t.byteLength=r,t.toByteArray=i,t.fromByteArray=s;for(var u=[],c=[],l="undefined"!=typeof Uint8Array?Uint8Array:Array,p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=0,h=p.length;f>1,l=-7,p=n?i-1:0,f=n?-1:1,h=e[t+p];for(p+=f,o=h&(1<<-l)-1,h>>=-l,l+=s;l>0;o=256*o+e[t+p],p+=f,l-=8);for(a=o&(1<<-l)-1,o>>=-l,l+=r;l>0;a=256*a+e[t+p],p+=f,l-=8);if(0===o)o=1-c;else{if(o===u)return a?NaN:(h?-1:1)*(1/0);a+=Math.pow(2,r),o-=c}return(h?-1:1)*a*Math.pow(2,o-r)},t.write=function(e,t,n,r,i,o){var a,s,u,c=8*o-i-1,l=(1<>1,f=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,h=r?0:o-1,d=r?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-a))<1&&(a--,u*=2),t+=a+p>=1?f/u:f*Math.pow(2,1-p),t*u>=2&&(a++,u/=2),a+p>=l?(s=0,a=l):a+p>=1?(s=(t*u-1)*Math.pow(2,i),a+=p):(s=t*Math.pow(2,p-1)*Math.pow(2,i),a=0));i>=8;e[n+h]=255&s,h+=d,s/=256,i-=8);for(a=a<0;e[n+h]=255&a,h+=d,a/=256,c-=8);e[n+h-d]|=128*m}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t,n){var r=[(0,E.systemThunkMiddleware)(n)],i=S.default.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__||d.compose;return(0,d.createStore)(e,t,i(d.applyMiddleware.apply(void 0,r)))}function s(e,t){return(0,E.isObject)(e)&&!(0,E.isArray)(e)?e:(0,E.isFunc)(e)?s(e(t),t):(0,E.isArray)(e)?e.map(function(e){return s(e,t)}).reduce(u,{}):{}}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!(0,E.isObject)(e))return{};if(!(0,E.isObject)(t))return e;var n=e.statePlugins;if((0,E.isObject)(n))for(var r in n){var i=n[r];if((0,E.isObject)(i)&&(0,E.isObject)(i.wrapActions)){var o=i.wrapActions;for(var a in o){var s=o[a];Array.isArray(s)||(s=[s],o[a]=s),t&&t.statePlugins&&t.statePlugins[r]&&t.statePlugins[r].wrapActions&&t.statePlugins[r].wrapActions[a]&&(t.statePlugins[r].wrapActions[a]=o[a].concat(t.statePlugins[r].wrapActions[a]))}}}return(0,g.default)(e,t)}function c(e){var t=(0,E.objMap)(e,function(e){return e.reducers});return l(t)}function l(e){var t=Object.keys(e).reduce(function(t,n){return t[n]=p(e[n]),t},{});return Object.keys(t).length?(0,_.combineReducers)(t):C}function p(e){return function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:new m.Map,n=arguments[1];if(!e)return t;var r=e[n.type];return r?r(t,n):t}}function f(e,t,n){var r=a(e,t,n);return r}Object.defineProperty(t,"__esModule",{value:!0});var h=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};o(this,e),(0,g.default)(this,{state:{},plugins:[],system:{configs:{},fn:{},components:{},rootInjects:{},statePlugins:{}},boundSystem:{},toolbox:{}},t),this.getSystem=this._getSystem.bind(this),this.store=f(C,(0,m.fromJS)(this.state),this.getSystem),this.buildSystem(!1),this.register(this.plugins)}return h(e,[{key:"getStore",value:function(){return this.store}},{key:"register",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=s(e,this.getSystem());u(this.system,n),t&&this.buildSystem()}},{key:"buildSystem",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.getStore().dispatch,n=this.getStore().getState;this.boundSystem=Object.assign({},this.getRootInjects(),this.getWrappedAndBoundActions(t),this.getBoundSelectors(n,this.getSystem),this.getStateThunks(n),this.getFn(),this.getConfigs()),e&&this.rebuildReducer()}},{key:"_getSystem",value:function(){return this.boundSystem}},{key:"getRootInjects",value:function(){return Object.assign({getSystem:this.getSystem,getStore:this.getStore.bind(this),getComponents:this.getComponents.bind(this),getState:this.getStore().getState,getConfigs:this._getConfigs.bind(this),Im:y.default},this.system.rootInjects||{})}},{key:"_getConfigs",value:function(){return this.system.configs}},{key:"getConfigs",value:function(){return{configs:this.system.configs}}},{key:"setConfigs",value:function(e){this.system.configs=e}},{key:"rebuildReducer",value:function(){this.store.replaceReducer(c(this.system.statePlugins))}},{key:"getType",value:function(e){var t=e[0].toUpperCase()+e.slice(1);return(0,E.objReduce)(this.system.statePlugins,function(n,r){var o=n[e];if(o)return i({},r+t,o)})}},{key:"getSelectors",value:function(){return this.getType("selectors")}},{key:"getActions",value:function(){var e=this.getType("actions");return(0,E.objMap)(e,function(e){return(0,E.objReduce)(e,function(e,t){if((0,E.isFn)(e))return i({},t,e)})})}},{key:"getWrappedAndBoundActions",value:function(e){var t=this,n=this.getBoundActions(e);return(0,E.objMap)(n,function(e,n){var r=t.system.statePlugins[n.slice(0,-7)].wrapActions;return r?(0,E.objMap)(e,function(e,n){var i=r[n];return i?(Array.isArray(i)||(i=[i]),i.reduce(function(e,n){var r=function(){return n(e,t.getSystem()).apply(void 0,arguments)};if(!(0,E.isFn)(r))throw new TypeError("wrapActions needs to return a function that returns a new function (ie the wrapped action)");return r},e||Function.prototype)):e}):e})}},{key:"getStates",value:function(e){return Object.keys(this.system.statePlugins).reduce(function(t,n){return t[n]=e.get(n),t},{})}},{key:"getStateThunks",value:function(e){return Object.keys(this.system.statePlugins).reduce(function(t,n){return t[n]=function(){return e().get(n)},t},{})}},{key:"getFn",value:function(){return{fn:this.system.fn}}},{key:"getComponents",value:function(e){return"undefined"!=typeof e?this.system.components[e]:this.system.components}},{key:"getBoundSelectors",value:function(e,t){return(0,E.objMap)(this.getSelectors(),function(n,r){var i=[r.slice(0,-9)],o=function(){return e().getIn(i)};return(0,E.objMap)(n,function(e){return function(){for(var n=arguments.length,r=Array(n),i=0;i>>0;if(""+n!==t||4294967295===n)return NaN;t=n}return t<0?d(e)+t:t}function y(){return!0}function v(e,t,n){return(0===e||void 0!==n&&e<=-n)&&(void 0===t||void 0!==n&&t>=n)}function g(e,t){return b(e,t,0)}function _(e,t){return b(e,t,t)}function b(e,t,n){return void 0===e?n:e<0?Math.max(0,t+e):void 0===t?e:Math.min(t,e)}function w(e){this.next=e}function x(e,t,n,r){var i=0===e?t:1===e?n:[t,n];return r?r.value=i:r={value:i,done:!1},r}function k(){return{value:void 0,done:!0}}function S(e){return!!A(e)}function E(e){return e&&"function"==typeof e.next}function C(e){var t=A(e);return t&&t.call(e)}function A(e){var t=e&&(kn&&e[kn]||e[Sn]);if("function"==typeof t)return t}function T(e){return e&&"number"==typeof e.length}function O(e){return null===e||void 0===e?N():o(e)?e.toSeq():U(e)}function D(e){return null===e||void 0===e?N().toKeyedSeq():o(e)?a(e)?e.toSeq():e.fromEntrySeq():z(e)}function M(e){return null===e||void 0===e?N():o(e)?a(e)?e.entrySeq():e.toIndexedSeq():L(e)}function P(e){return(null===e||void 0===e?N():o(e)?a(e)?e.entrySeq():e:L(e)).toSetSeq()}function I(e){this._array=e,this.size=e.length}function j(e){var t=Object.keys(e);this._object=e,this._keys=t,this.size=t.length}function R(e){this._iterable=e,this.size=e.length||e.size}function F(e){this._iterator=e,this._iteratorCache=[]}function B(e){return!(!e||!e[Cn])}function N(){return An||(An=new I([]))}function z(e){var t=Array.isArray(e)?new I(e).fromEntrySeq():E(e)?new F(e).fromEntrySeq():S(e)?new R(e).fromEntrySeq():"object"==typeof e?new j(e):void 0;if(!t)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+e);return t}function L(e){var t=q(e);if(!t)throw new TypeError("Expected Array or iterable object of values: "+e);return t}function U(e){var t=q(e)||"object"==typeof e&&new j(e);if(!t)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+e);return t}function q(e){return T(e)?new I(e):E(e)?new F(e):S(e)?new R(e):void 0}function W(e,t,n,r){var i=e._cache;if(i){for(var o=i.length-1,a=0;a<=o;a++){var s=i[n?o-a:a];if(t(s[1],r?s[0]:a,e)===!1)return a+1}return a}return e.__iterateUncached(t,n)}function K(e,t,n,r){var i=e._cache;if(i){var o=i.length-1,a=0;return new w(function(){var e=i[n?o-a:a];return a++>o?k():x(t,r?e[0]:a-1,e[1])})}return e.__iteratorUncached(t,n)}function V(e,t){return t?H(t,e,"",{"":e}):J(e)}function H(e,t,n,r){return Array.isArray(t)?e.call(r,n,M(t).map(function(n,r){return H(e,n,r,t)})):G(t)?e.call(r,n,D(t).map(function(n,r){return H(e,n,r,t)})):t}function J(e){return Array.isArray(e)?M(e).map(J).toList():G(e)?D(e).map(J).toMap():e}function G(e){return e&&(e.constructor===Object||void 0===e.constructor)}function X(e,t){if(e===t||e!==e&&t!==t)return!0;if(!e||!t)return!1;if("function"==typeof e.valueOf&&"function"==typeof t.valueOf){if(e=e.valueOf(),t=t.valueOf(),e===t||e!==e&&t!==t)return!0;if(!e||!t)return!1}return!("function"!=typeof e.equals||"function"!=typeof t.equals||!e.equals(t))}function Y(e,t){if(e===t)return!0;if(!o(t)||void 0!==e.size&&void 0!==t.size&&e.size!==t.size||void 0!==e.__hash&&void 0!==t.__hash&&e.__hash!==t.__hash||a(e)!==a(t)||s(e)!==s(t)||c(e)!==c(t))return!1;if(0===e.size&&0===t.size)return!0;var n=!u(e);if(c(e)){var r=e.entries();return t.every(function(e,t){var i=r.next().value;return i&&X(i[1],e)&&(n||X(i[0],t))})&&r.next().done}var i=!1;if(void 0===e.size)if(void 0===t.size)"function"==typeof e.cacheResult&&e.cacheResult();else{i=!0;var l=e;e=t,t=l}var p=!0,f=t.__iterate(function(t,r){if(n?!e.has(t):i?!X(t,e.get(r,vn)):!X(e.get(r,vn),t))return p=!1,!1});return p&&e.size===f}function $(e,t){if(!(this instanceof $))return new $(e,t);if(this._value=e,this.size=void 0===t?1/0:Math.max(0,t),0===this.size){if(Tn)return Tn;Tn=this}}function Z(e,t){if(!e)throw new Error(t)}function Q(e,t,n){if(!(this instanceof Q))return new Q(e,t,n);if(Z(0!==n,"Cannot step a Range by 0"),e=e||0,void 0===t&&(t=1/0),n=void 0===n?1:Math.abs(n),t>>1&1073741824|3221225471&e}function oe(e){if(e===!1||null===e||void 0===e)return 0;if("function"==typeof e.valueOf&&(e=e.valueOf(),e===!1||null===e||void 0===e))return 0;if(e===!0)return 1;var t=typeof e;if("number"===t){if(e!==e||e===1/0)return 0;var n=0|e;for(n!==e&&(n^=4294967295*e);e>4294967295;)e/=4294967295,n^=e;return ie(n)}if("string"===t)return e.length>Bn?ae(e):se(e);if("function"==typeof e.hashCode)return e.hashCode();if("object"===t)return ue(e);if("function"==typeof e.toString)return se(e.toString());throw new Error("Value type "+t+" cannot be hashed.")}function ae(e){var t=Ln[e];return void 0===t&&(t=se(e),zn===Nn&&(zn=0,Ln={}),zn++,Ln[e]=t),t}function se(e){for(var t=0,n=0;n0)switch(e.nodeType){case 1:return e.uniqueID;case 9:return e.documentElement&&e.documentElement.uniqueID}}function le(e){Z(e!==1/0,"Cannot perform this action with an infinite size.")}function pe(e){return null===e||void 0===e?xe():fe(e)&&!c(e)?e:xe().withMutations(function(t){var r=n(e);le(r.size),r.forEach(function(e,n){return t.set(n,e)})})}function fe(e){return!(!e||!e[Un])}function he(e,t){this.ownerID=e,this.entries=t}function de(e,t,n){this.ownerID=e,this.bitmap=t,this.nodes=n}function me(e,t,n){this.ownerID=e,this.count=t,this.nodes=n}function ye(e,t,n){this.ownerID=e,this.keyHash=t,this.entries=n}function ve(e,t,n){this.ownerID=e,this.keyHash=t,this.entry=n}function ge(e,t,n){this._type=t,this._reverse=n,this._stack=e._root&&be(e._root)}function _e(e,t){return x(e,t[0],t[1])}function be(e,t){return{node:e,index:0,__prev:t}}function we(e,t,n,r){var i=Object.create(qn);return i.size=e,i._root=t,i.__ownerID=n,i.__hash=r,i.__altered=!1,i}function xe(){return Wn||(Wn=we(0))}function ke(e,t,n){var r,i;if(e._root){var o=l(gn),a=l(_n);if(r=Se(e._root,e.__ownerID,0,void 0,t,n,o,a),!a.value)return e;i=e.size+(o.value?n===vn?-1:1:0)}else{if(n===vn)return e;i=1,r=new he(e.__ownerID,[[t,n]])}return e.__ownerID?(e.size=i,e._root=r,e.__hash=void 0,e.__altered=!0,e):r?we(i,r):xe()}function Se(e,t,n,r,i,o,a,s){return e?e.update(t,n,r,i,o,a,s):o===vn?e:(p(s),p(a),new ve(t,r,[i,o]))}function Ee(e){return e.constructor===ve||e.constructor===ye}function Ce(e,t,n,r,i){if(e.keyHash===r)return new ye(t,r,[e.entry,i]);var o,a=(0===n?e.keyHash:e.keyHash>>>n)&yn,s=(0===n?r:r>>>n)&yn,u=a===s?[Ce(e,t,n+dn,r,i)]:(o=new ve(t,r,i),a>>=1)a[s]=1&n?t[o++]:void 0;return a[r]=i,new me(e,o+1,a)}function De(e,t,r){for(var i=[],a=0;a>1&1431655765,e=(858993459&e)+(e>>2&858993459),e=e+(e>>4)&252645135,e+=e>>8,e+=e>>16,127&e}function Fe(e,t,n,r){var i=r?e:h(e);return i[t]=n,i}function Be(e,t,n,r){var i=e.length+1;if(r&&t+1===i)return e[t]=n,e;for(var o=new Array(i),a=0,s=0;s0&&io?0:o-n,c=a-n;return c>mn&&(c=mn),function(){if(i===c)return Yn;var e=t?--c:i++;return r&&r[e]}}function i(e,r,i){var s,u=e&&e.array,c=i>o?0:o-i>>r,l=(a-i>>r)+1;return l>mn&&(l=mn),function(){for(;;){if(s){var e=s();if(e!==Yn)return e;s=null}if(c===l)return Yn;var o=t?--l:c++;s=n(u&&u[o],r-dn,i+(o<=e.size||t<0)return e.withMutations(function(e){t<0?Xe(e,t).set(0,n):Xe(e,0,t+1).set(t,n)});t+=e._origin;var r=e._tail,i=e._root,o=l(_n);return t>=$e(e._capacity)?r=He(r,e.__ownerID,0,t,n,o):i=He(i,e.__ownerID,e._level,t,n,o),o.value?e.__ownerID?(e._root=i,e._tail=r,e.__hash=void 0,e.__altered=!0,e):We(e._origin,e._capacity,e._level,i,r):e}function He(e,t,n,r,i,o){var a=r>>>n&yn,s=e&&a0){var c=e&&e.array[a],l=He(c,t,n-dn,r,i,o);return l===c?e:(u=Je(e,t),u.array[a]=l,u)}return s&&e.array[a]===i?e:(p(o),u=Je(e,t),void 0===i&&a===u.array.length-1?u.array.pop():u.array[a]=i,u)}function Je(e,t){return t&&e&&t===e.ownerID?e:new Ue(e?e.array.slice():[],t)}function Ge(e,t){if(t>=$e(e._capacity))return e._tail;if(t<1<0;)n=n.array[t>>>r&yn],r-=dn;return n}}function Xe(e,t,n){void 0!==t&&(t|=0),void 0!==n&&(n|=0);var r=e.__ownerID||new f,i=e._origin,o=e._capacity,a=i+t,s=void 0===n?o:n<0?o+n:i+n;if(a===i&&s===o)return e;if(a>=s)return e.clear();for(var u=e._level,c=e._root,l=0;a+l<0;)c=new Ue(c&&c.array.length?[void 0,c]:[],r),u+=dn,l+=1<=1<p?new Ue([],r):d;if(d&&h>p&&adn;v-=dn){var g=p>>>v&yn;y=y.array[g]=Je(y.array[g],r)}y.array[p>>>dn&yn]=d}if(s=h)a-=h,s-=h,u=dn,c=null,m=m&&m.removeBefore(r,0,a);else if(a>i||h>>u&yn;if(_!==h>>>u&yn)break;_&&(l+=(1<i&&(c=c.removeBefore(r,u,a-l)),c&&h
a&&(a=c.size),o(u)||(c=c.map(function(e){return V(e)})),i.push(c)}return a>e.size&&(e=e.setSize(a)),Ie(e,t,i)}function $e(e){return e>>dn<=mn&&a.size>=2*o.size?(i=a.filter(function(e,t){return void 0!==e&&s!==t}),r=i.toKeyedSeq().map(function(e){return e[0]}).flip().toMap(),e.__ownerID&&(r.__ownerID=i.__ownerID=e.__ownerID)):(r=o.remove(t),i=s===a.size-1?a.pop():a.set(s,void 0))}else if(u){if(n===a.get(s)[1])return e;r=o,i=a.set(s,[t,n])}else r=o.set(t,a.size),i=a.set(a.size,[t,n]);return e.__ownerID?(e.size=r.size,e._map=r,e._list=i,e.__hash=void 0,e):et(r,i)}function rt(e,t){this._iter=e,this._useKeys=t,this.size=e.size}function it(e){this._iter=e,this.size=e.size}function ot(e){this._iter=e,this.size=e.size}function at(e){this._iter=e,this.size=e.size}function st(e){var t=Tt(e);return t._iter=e,t.size=e.size,t.flip=function(){return e},t.reverse=function(){var t=e.reverse.apply(this);return t.flip=function(){return e.reverse()},t},t.has=function(t){return e.includes(t)},t.includes=function(t){return e.has(t)},t.cacheResult=Ot,t.__iterateUncached=function(t,n){var r=this;return e.__iterate(function(e,n){return t(n,e,r)!==!1},n)},t.__iteratorUncached=function(t,n){if(t===xn){var r=e.__iterator(t,n);return new w(function(){var e=r.next();if(!e.done){var t=e.value[0];e.value[0]=e.value[1],e.value[1]=t}return e})}return e.__iterator(t===wn?bn:wn,n)},t}function ut(e,t,n){var r=Tt(e);return r.size=e.size,r.has=function(t){return e.has(t)},r.get=function(r,i){var o=e.get(r,vn);return o===vn?i:t.call(n,o,r,e)},r.__iterateUncached=function(r,i){var o=this;return e.__iterate(function(e,i,a){return r(t.call(n,e,i,a),i,o)!==!1},i)},r.__iteratorUncached=function(r,i){var o=e.__iterator(xn,i);return new w(function(){var i=o.next();if(i.done)return i;var a=i.value,s=a[0];return x(r,s,t.call(n,a[1],s,e),i)})},r}function ct(e,t){var n=Tt(e);return n._iter=e,n.size=e.size,n.reverse=function(){return e},e.flip&&(n.flip=function(){var t=st(e);return t.reverse=function(){return e.flip()},t}),n.get=function(n,r){return e.get(t?n:-1-n,r)},n.has=function(n){return e.has(t?n:-1-n)},n.includes=function(t){return e.includes(t)},n.cacheResult=Ot,n.__iterate=function(t,n){var r=this;return e.__iterate(function(e,n){return t(e,n,r)},!n)},n.__iterator=function(t,n){return e.__iterator(t,!n)},n}function lt(e,t,n,r){var i=Tt(e);return r&&(i.has=function(r){var i=e.get(r,vn);return i!==vn&&!!t.call(n,i,r,e)},i.get=function(r,i){var o=e.get(r,vn);return o!==vn&&t.call(n,o,r,e)?o:i}),i.__iterateUncached=function(i,o){var a=this,s=0;return e.__iterate(function(e,o,u){if(t.call(n,e,o,u))return s++,i(e,r?o:s-1,a)},o),s},i.__iteratorUncached=function(i,o){var a=e.__iterator(xn,o),s=0;return new w(function(){for(;;){var o=a.next();if(o.done)return o;var u=o.value,c=u[0],l=u[1];if(t.call(n,l,c,e))return x(i,r?c:s++,l,o)}})},i}function pt(e,t,n){var r=pe().asMutable();return e.__iterate(function(i,o){r.update(t.call(n,i,o,e),0,function(e){return e+1})}),r.asImmutable()}function ft(e,t,n){var r=a(e),i=(c(e)?Ze():pe()).asMutable();e.__iterate(function(o,a){i.update(t.call(n,o,a,e),function(e){return e=e||[],e.push(r?[a,o]:o),e})});var o=At(e);return i.map(function(t){return St(e,o(t))})}function ht(e,t,n,r){var i=e.size;if(void 0!==t&&(t|=0),void 0!==n&&(n===1/0?n=i:n|=0),v(t,n,i))return e;var o=g(t,i),a=_(n,i);if(o!==o||a!==a)return ht(e.toSeq().cacheResult(),t,n,r);var s,u=a-o;u===u&&(s=u<0?0:u);var c=Tt(e);return c.size=0===s?s:e.size&&s||void 0,!r&&B(e)&&s>=0&&(c.get=function(t,n){return t=m(this,t),t>=0&&ts)return k();var e=i.next();return r||t===wn?e:t===bn?x(t,u-1,void 0,e):x(t,u-1,e.value[1],e)})},c}function dt(e,t,n){var r=Tt(e);return r.__iterateUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterate(r,i);var a=0;return e.__iterate(function(e,i,s){return t.call(n,e,i,s)&&++a&&r(e,i,o)}),a},r.__iteratorUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterator(r,i);var a=e.__iterator(xn,i),s=!0;return new w(function(){if(!s)return k();var e=a.next();if(e.done)return e;var i=e.value,u=i[0],c=i[1];return t.call(n,c,u,o)?r===xn?e:x(r,u,c,e):(s=!1,k())})},r}function mt(e,t,n,r){var i=Tt(e);return i.__iterateUncached=function(i,o){var a=this;if(o)return this.cacheResult().__iterate(i,o);var s=!0,u=0;return e.__iterate(function(e,o,c){if(!s||!(s=t.call(n,e,o,c)))return u++,i(e,r?o:u-1,a)}),u},i.__iteratorUncached=function(i,o){var a=this;if(o)return this.cacheResult().__iterator(i,o);var s=e.__iterator(xn,o),u=!0,c=0;return new w(function(){var e,o,l;do{if(e=s.next(),e.done)return r||i===wn?e:i===bn?x(i,c++,void 0,e):x(i,c++,e.value[1],e);var p=e.value;o=p[0],l=p[1],u&&(u=t.call(n,l,o,a))}while(u);return i===xn?e:x(i,o,l,e)})},i}function yt(e,t){var r=a(e),i=[e].concat(t).map(function(e){return o(e)?r&&(e=n(e)):e=r?z(e):L(Array.isArray(e)?e:[e]),e}).filter(function(e){return 0!==e.size});if(0===i.length)return e;if(1===i.length){var u=i[0];if(u===e||r&&a(u)||s(e)&&s(u))return u}var c=new I(i);return r?c=c.toKeyedSeq():s(e)||(c=c.toSetSeq()),c=c.flatten(!0),c.size=i.reduce(function(e,t){if(void 0!==e){var n=t.size;if(void 0!==n)return e+n}},0),c}function vt(e,t,n){var r=Tt(e);return r.__iterateUncached=function(r,i){function a(e,c){var l=this;e.__iterate(function(e,i){return(!t||c0}function kt(e,n,r){var i=Tt(e);return i.size=new I(r).map(function(e){return e.size}).min(),i.__iterate=function(e,t){for(var n,r=this.__iterator(wn,t),i=0;!(n=r.next()).done&&e(n.value,i++,this)!==!1;);return i},i.__iteratorUncached=function(e,i){var o=r.map(function(e){return e=t(e),C(i?e.reverse():e)}),a=0,s=!1;return new w(function(){var t;return s||(t=o.map(function(e){return e.next()}),s=t.some(function(e){return e.done})),s?k():x(e,a++,n.apply(null,t.map(function(e){return e.value})))})},i}function St(e,t){return B(e)?t:e.constructor(t)}function Et(e){if(e!==Object(e))throw new TypeError("Expected [K, V] tuple: "+e)}function Ct(e){return le(e.size),d(e)}function At(e){return a(e)?n:s(e)?r:i}function Tt(e){return Object.create((a(e)?D:s(e)?M:P).prototype)}function Ot(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):O.prototype.cacheResult.call(this)}function Dt(e,t){return e>t?1:et?-1:0}function on(e){if(e.size===1/0)return 0;var t=c(e),n=a(e),r=t?1:0,i=e.__iterate(n?t?function(e,t){r=31*r+sn(oe(e),oe(t))|0}:function(e,t){r=r+sn(oe(e),oe(t))|0}:t?function(e){r=31*r+oe(e)|0}:function(e){r=r+oe(e)|0});return an(i,r)}function an(e,t){return t=Mn(t,3432918353),t=Mn(t<<15|t>>>-15,461845907),t=Mn(t<<13|t>>>-13,5),t=(t+3864292196|0)^e,t=Mn(t^t>>>16,2246822507),t=Mn(t^t>>>13,3266489909),t=ie(t^t>>>16)}function sn(e,t){return e^t+2654435769+(e<<6)+(e>>2)|0}var un=Array.prototype.slice;e(n,t),e(r,t),e(i,t),t.isIterable=o,t.isKeyed=a,t.isIndexed=s,t.isAssociative=u,t.isOrdered=c,t.Keyed=n,t.Indexed=r,t.Set=i;var cn="@@__IMMUTABLE_ITERABLE__@@",ln="@@__IMMUTABLE_KEYED__@@",pn="@@__IMMUTABLE_INDEXED__@@",fn="@@__IMMUTABLE_ORDERED__@@",hn="delete",dn=5,mn=1<r?k():x(e,i,n[t?r-i++:i++])})},e(j,D),j.prototype.get=function(e,t){return void 0===t||this.has(e)?this._object[e]:t},j.prototype.has=function(e){return this._object.hasOwnProperty(e)},j.prototype.__iterate=function(e,t){for(var n=this._object,r=this._keys,i=r.length-1,o=0;o<=i;o++){var a=r[t?i-o:o];if(e(n[a],a,this)===!1)return o+1}return o},j.prototype.__iterator=function(e,t){var n=this._object,r=this._keys,i=r.length-1,o=0;return new w(function(){var a=r[t?i-o:o];return o++>i?k():x(e,a,n[a])})},j.prototype[fn]=!0,e(R,M),R.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);var n=this._iterable,r=C(n),i=0;if(E(r))for(var o;!(o=r.next()).done&&e(o.value,i++,this)!==!1;);return i},R.prototype.__iteratorUncached=function(e,t){if(t)return this.cacheResult().__iterator(e,t);var n=this._iterable,r=C(n);if(!E(r))return new w(k);var i=0;return new w(function(){var t=r.next();return t.done?t:x(e,i++,t.value)})},e(F,M),F.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);for(var n=this._iterator,r=this._iteratorCache,i=0;i=r.length){var t=n.next();if(t.done)return t;r[i]=t.value}return x(e,i,r[i++])})};var An;e($,M),$.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},$.prototype.get=function(e,t){return this.has(e)?this._value:t},$.prototype.includes=function(e){return X(this._value,e)},$.prototype.slice=function(e,t){var n=this.size;return v(e,t,n)?this:new $(this._value,_(t,n)-g(e,n))},$.prototype.reverse=function(){return this},$.prototype.indexOf=function(e){return X(this._value,e)?0:-1},$.prototype.lastIndexOf=function(e){return X(this._value,e)?this.size:-1},$.prototype.__iterate=function(e,t){
+for(var n=0;n=0&&t=0&&nn?k():x(e,o++,a)})},Q.prototype.equals=function(e){return e instanceof Q?this._start===e._start&&this._end===e._end&&this._step===e._step:Y(this,e)};var On;e(ee,t),e(te,ee),e(ne,ee),e(re,ee),ee.Keyed=te,ee.Indexed=ne,ee.Set=re;var Dn,Mn="function"==typeof Math.imul&&Math.imul(4294967295,2)===-2?Math.imul:function(e,t){e|=0,t|=0;var n=65535&e,r=65535&t;return n*r+((e>>>16)*r+n*(t>>>16)<<16>>>0)|0},Pn=Object.isExtensible,In=function(){try{return Object.defineProperty({},"@",{}),!0}catch(e){return!1}}(),jn="function"==typeof WeakMap;jn&&(Dn=new WeakMap);var Rn=0,Fn="__immutablehash__";"function"==typeof Symbol&&(Fn=Symbol(Fn));var Bn=16,Nn=255,zn=0,Ln={};e(pe,te),pe.of=function(){var e=un.call(arguments,0);return xe().withMutations(function(t){for(var n=0;n=e.length)throw new Error("Missing value for key: "+e[n]);t.set(e[n],e[n+1])}})},pe.prototype.toString=function(){return this.__toString("Map {","}")},pe.prototype.get=function(e,t){return this._root?this._root.get(0,void 0,e,t):t},pe.prototype.set=function(e,t){return ke(this,e,t)},pe.prototype.setIn=function(e,t){return this.updateIn(e,vn,function(){return t})},pe.prototype.remove=function(e){return ke(this,e,vn)},pe.prototype.deleteIn=function(e){return this.updateIn(e,function(){return vn})},pe.prototype.update=function(e,t,n){return 1===arguments.length?e(this):this.updateIn([e],t,n)},pe.prototype.updateIn=function(e,t,n){n||(n=t,t=void 0);var r=je(this,Mt(e),t,n);return r===vn?void 0:r},pe.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):xe()},pe.prototype.merge=function(){return De(this,void 0,arguments)},pe.prototype.mergeWith=function(e){var t=un.call(arguments,1);return De(this,e,t)},pe.prototype.mergeIn=function(e){var t=un.call(arguments,1);return this.updateIn(e,xe(),function(e){return"function"==typeof e.merge?e.merge.apply(e,t):t[t.length-1]})},pe.prototype.mergeDeep=function(){return De(this,Me,arguments)},pe.prototype.mergeDeepWith=function(e){var t=un.call(arguments,1);return De(this,Pe(e),t)},pe.prototype.mergeDeepIn=function(e){var t=un.call(arguments,1);return this.updateIn(e,xe(),function(e){return"function"==typeof e.mergeDeep?e.mergeDeep.apply(e,t):t[t.length-1]})},pe.prototype.sort=function(e){return Ze(bt(this,e))},pe.prototype.sortBy=function(e,t){return Ze(bt(this,t,e))},pe.prototype.withMutations=function(e){var t=this.asMutable();return e(t),t.wasAltered()?t.__ensureOwner(this.__ownerID):this},pe.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new f)},pe.prototype.asImmutable=function(){return this.__ensureOwner()},pe.prototype.wasAltered=function(){return this.__altered},pe.prototype.__iterator=function(e,t){return new ge(this,e,t)},pe.prototype.__iterate=function(e,t){var n=this,r=0;return this._root&&this._root.iterate(function(t){return r++,e(t[1],t[0],n)},t),r},pe.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?we(this.size,this._root,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},pe.isMap=fe;var Un="@@__IMMUTABLE_MAP__@@",qn=pe.prototype;qn[Un]=!0,qn[hn]=qn.remove,qn.removeIn=qn.deleteIn,he.prototype.get=function(e,t,n,r){for(var i=this.entries,o=0,a=i.length;o=Kn)return Ae(e,u,r,i);var d=e&&e===this.ownerID,m=d?u:h(u);return f?s?c===l-1?m.pop():m[c]=m.pop():m[c]=[r,i]:m.push([r,i]),d?(this.entries=m,this):new he(e,m)}},de.prototype.get=function(e,t,n,r){void 0===t&&(t=oe(n));var i=1<<((0===e?t:t>>>e)&yn),o=this.bitmap;return 0===(o&i)?r:this.nodes[Re(o&i-1)].get(e+dn,t,n,r)},de.prototype.update=function(e,t,n,r,i,o,a){void 0===n&&(n=oe(r));var s=(0===t?n:n>>>t)&yn,u=1<=Vn)return Oe(e,f,c,s,d);if(l&&!d&&2===f.length&&Ee(f[1^p]))return f[1^p];if(l&&d&&1===f.length&&Ee(d))return d;var m=e&&e===this.ownerID,y=l?d?c:c^u:c|u,v=l?d?Fe(f,p,d,m):Ne(f,p,m):Be(f,p,d,m);return m?(this.bitmap=y,this.nodes=v,this):new de(e,y,v)},me.prototype.get=function(e,t,n,r){void 0===t&&(t=oe(n));var i=(0===e?t:t>>>e)&yn,o=this.nodes[i];return o?o.get(e+dn,t,n,r):r},me.prototype.update=function(e,t,n,r,i,o,a){void 0===n&&(n=oe(r));var s=(0===t?n:n>>>t)&yn,u=i===vn,c=this.nodes,l=c[s];if(u&&!l)return this;var p=Se(l,e,t+dn,n,r,i,o,a);if(p===l)return this;var f=this.count;if(l){if(!p&&(f--,f=0&&e>>t&yn;if(r>=this.array.length)return new Ue([],e);var i,o=0===r;if(t>0){var a=this.array[r];if(i=a&&a.removeBefore(e,t-dn,n),i===a&&o)return this}if(o&&!i)return this;var s=Je(this,e);if(!o)for(var u=0;u>>t&yn;if(r>=this.array.length)return this;var i;if(t>0){var o=this.array[r];if(i=o&&o.removeAfter(e,t-dn,n),i===o&&r===this.array.length-1)return this}var a=Je(this,e);return a.array.splice(r+1),i&&(a.array[r]=i),a};var Xn,Yn={};e(Ze,pe),Ze.of=function(){return this(arguments)},Ze.prototype.toString=function(){return this.__toString("OrderedMap {","}")},Ze.prototype.get=function(e,t){var n=this._map.get(e);return void 0!==n?this._list.get(n)[1]:t},Ze.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._map.clear(),this._list.clear(),this):tt()},Ze.prototype.set=function(e,t){return nt(this,e,t)},Ze.prototype.remove=function(e){return nt(this,e,vn)},Ze.prototype.wasAltered=function(){return this._map.wasAltered()||this._list.wasAltered()},Ze.prototype.__iterate=function(e,t){var n=this;return this._list.__iterate(function(t){return t&&e(t[1],t[0],n)},t)},Ze.prototype.__iterator=function(e,t){return this._list.fromEntrySeq().__iterator(e,t)},Ze.prototype.__ensureOwner=function(e){if(e===this.__ownerID)return this;var t=this._map.__ensureOwner(e),n=this._list.__ensureOwner(e);return e?et(t,n,e,this.__hash):(this.__ownerID=e,this._map=t,this._list=n,this)},Ze.isOrderedMap=Qe,Ze.prototype[fn]=!0,Ze.prototype[hn]=Ze.prototype.remove;var $n;e(rt,D),rt.prototype.get=function(e,t){return this._iter.get(e,t)},rt.prototype.has=function(e){return this._iter.has(e)},rt.prototype.valueSeq=function(){return this._iter.valueSeq()},rt.prototype.reverse=function(){var e=this,t=ct(this,!0);return this._useKeys||(t.valueSeq=function(){return e._iter.toSeq().reverse()}),t},rt.prototype.map=function(e,t){var n=this,r=ut(this,e,t);return this._useKeys||(r.valueSeq=function(){return n._iter.toSeq().map(e,t)}),r},rt.prototype.__iterate=function(e,t){var n,r=this;return this._iter.__iterate(this._useKeys?function(t,n){return e(t,n,r)}:(n=t?Ct(this):0,function(i){return e(i,t?--n:n++,r)}),t)},rt.prototype.__iterator=function(e,t){if(this._useKeys)return this._iter.__iterator(e,t);var n=this._iter.__iterator(wn,t),r=t?Ct(this):0;return new w(function(){var i=n.next();return i.done?i:x(e,t?--r:r++,i.value,i)})},rt.prototype[fn]=!0,e(it,M),it.prototype.includes=function(e){return this._iter.includes(e)},it.prototype.__iterate=function(e,t){var n=this,r=0;return this._iter.__iterate(function(t){return e(t,r++,n)},t)},it.prototype.__iterator=function(e,t){var n=this._iter.__iterator(wn,t),r=0;return new w(function(){var t=n.next();return t.done?t:x(e,r++,t.value,t)})},e(ot,P),ot.prototype.has=function(e){return this._iter.includes(e)},ot.prototype.__iterate=function(e,t){var n=this;return this._iter.__iterate(function(t){return e(t,t,n)},t)},ot.prototype.__iterator=function(e,t){var n=this._iter.__iterator(wn,t);return new w(function(){var t=n.next();return t.done?t:x(e,t.value,t.value,t)})},e(at,D),at.prototype.entrySeq=function(){return this._iter.toSeq()},at.prototype.__iterate=function(e,t){var n=this;return this._iter.__iterate(function(t){if(t){Et(t);var r=o(t);return e(r?t.get(1):t[1],r?t.get(0):t[0],n)}},t)},at.prototype.__iterator=function(e,t){var n=this._iter.__iterator(wn,t);return new w(function(){for(;;){var t=n.next();if(t.done)return t;var r=t.value;if(r){Et(r);var i=o(r);return x(e,i?r.get(0):r[0],i?r.get(1):r[1],t)}}})},it.prototype.cacheResult=rt.prototype.cacheResult=ot.prototype.cacheResult=at.prototype.cacheResult=Ot,e(Pt,te),Pt.prototype.toString=function(){return this.__toString(jt(this)+" {","}")},Pt.prototype.has=function(e){return this._defaultValues.hasOwnProperty(e)},Pt.prototype.get=function(e,t){if(!this.has(e))return t;var n=this._defaultValues[e];return this._map?this._map.get(e,n):n},Pt.prototype.clear=function(){if(this.__ownerID)return this._map&&this._map.clear(),this;var e=this.constructor;return e._empty||(e._empty=It(this,xe()))},Pt.prototype.set=function(e,t){if(!this.has(e))throw new Error('Cannot set unknown key "'+e+'" on '+jt(this));if(this._map&&!this._map.has(e)){var n=this._defaultValues[e];if(t===n)return this}var r=this._map&&this._map.set(e,t);return this.__ownerID||r===this._map?this:It(this,r)},Pt.prototype.remove=function(e){if(!this.has(e))return this;var t=this._map&&this._map.remove(e);return this.__ownerID||t===this._map?this:It(this,t)},Pt.prototype.wasAltered=function(){return this._map.wasAltered()},Pt.prototype.__iterator=function(e,t){var r=this;return n(this._defaultValues).map(function(e,t){return r.get(t)}).__iterator(e,t)},Pt.prototype.__iterate=function(e,t){var r=this;return n(this._defaultValues).map(function(e,t){return r.get(t)}).__iterate(e,t)},Pt.prototype.__ensureOwner=function(e){if(e===this.__ownerID)return this;var t=this._map&&this._map.__ensureOwner(e);return e?It(this,t,e):(this.__ownerID=e,this._map=t,this)};var Zn=Pt.prototype;Zn[hn]=Zn.remove,Zn.deleteIn=Zn.removeIn=qn.removeIn,Zn.merge=qn.merge,Zn.mergeWith=qn.mergeWith,Zn.mergeIn=qn.mergeIn,Zn.mergeDeep=qn.mergeDeep,Zn.mergeDeepWith=qn.mergeDeepWith,Zn.mergeDeepIn=qn.mergeDeepIn,Zn.setIn=qn.setIn,Zn.update=qn.update,Zn.updateIn=qn.updateIn,Zn.withMutations=qn.withMutations,Zn.asMutable=qn.asMutable,Zn.asImmutable=qn.asImmutable,e(Bt,re),Bt.of=function(){return this(arguments)},Bt.fromKeys=function(e){return this(n(e).keySeq())},Bt.prototype.toString=function(){return this.__toString("Set {","}")},Bt.prototype.has=function(e){return this._map.has(e)},Bt.prototype.add=function(e){return zt(this,this._map.set(e,!0))},Bt.prototype.remove=function(e){return zt(this,this._map.remove(e))},Bt.prototype.clear=function(){return zt(this,this._map.clear())},Bt.prototype.union=function(){var e=un.call(arguments,0);return e=e.filter(function(e){return 0!==e.size}),0===e.length?this:0!==this.size||this.__ownerID||1!==e.length?this.withMutations(function(t){for(var n=0;n=0;n--)t={value:arguments[n],next:t};return this.__ownerID?(this.size=e,this._head=t,this.__hash=void 0,this.__altered=!0,this):Gt(e,t)},Ht.prototype.pushAll=function(e){if(e=r(e),0===e.size)return this;le(e.size);var t=this.size,n=this._head;return e.reverse().forEach(function(e){t++,n={value:e,next:n}}),this.__ownerID?(this.size=t,this._head=n,this.__hash=void 0,this.__altered=!0,this):Gt(t,n)},Ht.prototype.pop=function(){return this.slice(1)},Ht.prototype.unshift=function(){return this.push.apply(this,arguments)},Ht.prototype.unshiftAll=function(e){return this.pushAll(e)},Ht.prototype.shift=function(){return this.pop.apply(this,arguments)},Ht.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Xt()},Ht.prototype.slice=function(e,t){if(v(e,t,this.size))return this;var n=g(e,this.size),r=_(t,this.size);if(r!==this.size)return ne.prototype.slice.call(this,e,t);for(var i=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=i,this._head=o,this.__hash=void 0,this.__altered=!0,this):Gt(i,o)},Ht.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?Gt(this.size,this._head,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},Ht.prototype.__iterate=function(e,t){if(t)return this.reverse().__iterate(e);for(var n=0,r=this._head;r&&e(r.value,n++,this)!==!1;)r=r.next;return n},Ht.prototype.__iterator=function(e,t){if(t)return this.reverse().__iterator(e);var n=0,r=this._head;return new w(function(){if(r){var t=r.value;return r=r.next,x(e,n++,t)}return k()})},Ht.isStack=Jt;var ir="@@__IMMUTABLE_STACK__@@",or=Ht.prototype;or[ir]=!0,or.withMutations=qn.withMutations,or.asMutable=qn.asMutable,or.asImmutable=qn.asImmutable,or.wasAltered=qn.wasAltered;var ar;t.Iterator=w,Yt(t,{toArray:function(){le(this.size);var e=new Array(this.size||0);return this.valueSeq().__iterate(function(t,n){e[n]=t}),e},toIndexedSeq:function(){return new it(this)},toJS:function(){return this.toSeq().map(function(e){return e&&"function"==typeof e.toJS?e.toJS():e}).__toJS()},toJSON:function(){return this.toSeq().map(function(e){return e&&"function"==typeof e.toJSON?e.toJSON():e}).__toJS()},toKeyedSeq:function(){return new rt(this,!0)},toMap:function(){return pe(this.toKeyedSeq())},toObject:function(){le(this.size);var e={};return this.__iterate(function(t,n){e[n]=t}),e},toOrderedMap:function(){return Ze(this.toKeyedSeq())},toOrderedSet:function(){return qt(a(this)?this.valueSeq():this)},toSet:function(){return Bt(a(this)?this.valueSeq():this)},toSetSeq:function(){return new ot(this)},toSeq:function(){return s(this)?this.toIndexedSeq():a(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return Ht(a(this)?this.valueSeq():this)},toList:function(){return ze(a(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(e,t){return 0===this.size?e+t:e+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+t},concat:function(){var e=un.call(arguments,0);return St(this,yt(this,e))},includes:function(e){return this.some(function(t){return X(t,e)})},entries:function(){return this.__iterator(xn)},every:function(e,t){le(this.size);var n=!0;return this.__iterate(function(r,i,o){if(!e.call(t,r,i,o))return n=!1,!1}),n},filter:function(e,t){return St(this,lt(this,e,t,!0))},find:function(e,t,n){var r=this.findEntry(e,t);return r?r[1]:n},forEach:function(e,t){return le(this.size),this.__iterate(t?e.bind(t):e)},join:function(e){le(this.size),e=void 0!==e?""+e:",";var t="",n=!0;return this.__iterate(function(r){n?n=!1:t+=e,t+=null!==r&&void 0!==r?r.toString():""}),t},keys:function(){return this.__iterator(bn)},map:function(e,t){return St(this,ut(this,e,t))},reduce:function(e,t,n){le(this.size);var r,i;return arguments.length<2?i=!0:r=t,this.__iterate(function(t,o,a){i?(i=!1,r=t):r=e.call(n,r,t,o,a)}),r},reduceRight:function(e,t,n){var r=this.toKeyedSeq().reverse();return r.reduce.apply(r,arguments)},reverse:function(){return St(this,ct(this,!0))},slice:function(e,t){return St(this,ht(this,e,t,!0))},some:function(e,t){return!this.every(Qt(e),t)},sort:function(e){return St(this,bt(this,e))},values:function(){return this.__iterator(wn)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some(function(){return!0})},count:function(e,t){return d(e?this.toSeq().filter(e,t):this)},countBy:function(e,t){return pt(this,e,t)},equals:function(e){return Y(this,e)},entrySeq:function(){var e=this;if(e._cache)return new I(e._cache);var t=e.toSeq().map(Zt).toIndexedSeq();return t.fromEntrySeq=function(){return e.toSeq()},t},filterNot:function(e,t){return this.filter(Qt(e),t)},findEntry:function(e,t,n){var r=n;return this.__iterate(function(n,i,o){if(e.call(t,n,i,o))return r=[i,n],!1}),r},findKey:function(e,t){var n=this.findEntry(e,t);return n&&n[0]},findLast:function(e,t,n){return this.toKeyedSeq().reverse().find(e,t,n)},findLastEntry:function(e,t,n){return this.toKeyedSeq().reverse().findEntry(e,t,n)},findLastKey:function(e,t){return this.toKeyedSeq().reverse().findKey(e,t)},first:function(){return this.find(y)},flatMap:function(e,t){return St(this,gt(this,e,t))},flatten:function(e){return St(this,vt(this,e,!0))},fromEntrySeq:function(){return new at(this)},get:function(e,t){return this.find(function(t,n){return X(n,e)},void 0,t)},getIn:function(e,t){for(var n,r=this,i=Mt(e);!(n=i.next()).done;){var o=n.value;if(r=r&&r.get?r.get(o,vn):vn,r===vn)return t}return r},groupBy:function(e,t){return ft(this,e,t)},has:function(e){return this.get(e,vn)!==vn},hasIn:function(e){return this.getIn(e,vn)!==vn},isSubset:function(e){return e="function"==typeof e.includes?e:t(e),this.every(function(t){return e.includes(t)})},isSuperset:function(e){return e="function"==typeof e.isSubset?e:t(e),e.isSubset(this)},keyOf:function(e){return this.findKey(function(t){return X(t,e)})},keySeq:function(){return this.toSeq().map($t).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(e){return this.toKeyedSeq().reverse().keyOf(e)},max:function(e){return wt(this,e)},maxBy:function(e,t){return wt(this,t,e)},min:function(e){return wt(this,e?en(e):rn)},minBy:function(e,t){return wt(this,t?en(t):rn,e)},rest:function(){return this.slice(1)},skip:function(e){return this.slice(Math.max(0,e))},skipLast:function(e){return St(this,this.toSeq().reverse().skip(e).reverse())},skipWhile:function(e,t){return St(this,mt(this,e,t,!0))},skipUntil:function(e,t){return this.skipWhile(Qt(e),t)},sortBy:function(e,t){return St(this,bt(this,t,e))},take:function(e){return this.slice(0,Math.max(0,e))},takeLast:function(e){return St(this,this.toSeq().reverse().take(e).reverse())},takeWhile:function(e,t){return St(this,dt(this,e,t))},takeUntil:function(e,t){return this.takeWhile(Qt(e),t)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=on(this))}});var sr=t.prototype;sr[cn]=!0,sr[En]=sr.values,sr.__toJS=sr.toArray,sr.__toStringMapper=tn,sr.inspect=sr.toSource=function(){return this.toString()},sr.chain=sr.flatMap,sr.contains=sr.includes,Yt(n,{flip:function(){return St(this,st(this))},mapEntries:function(e,t){var n=this,r=0;return St(this,this.toSeq().map(function(i,o){return e.call(t,[o,i],r++,n)}).fromEntrySeq())},mapKeys:function(e,t){var n=this;return St(this,this.toSeq().flip().map(function(r,i){return e.call(t,r,i,n)}).flip())}});var ur=n.prototype;ur[ln]=!0,ur[En]=sr.entries,ur.__toJS=sr.toObject,ur.__toStringMapper=function(e,t){return JSON.stringify(t)+": "+tn(e)},Yt(r,{toKeyedSeq:function(){return new rt(this,!1)},filter:function(e,t){return St(this,lt(this,e,t,!1))},findIndex:function(e,t){var n=this.findEntry(e,t);return n?n[0]:-1},indexOf:function(e){var t=this.keyOf(e);return void 0===t?-1:t},lastIndexOf:function(e){var t=this.lastKeyOf(e);return void 0===t?-1:t},reverse:function(){return St(this,ct(this,!1))},slice:function(e,t){return St(this,ht(this,e,t,!1))},splice:function(e,t){var n=arguments.length;if(t=Math.max(0|t,0),0===n||2===n&&!t)return this;e=g(e,e<0?this.count():this.size);var r=this.slice(0,e);return St(this,1===n?r:r.concat(h(arguments,2),this.slice(e+t)))},findLastIndex:function(e,t){var n=this.findLastEntry(e,t);return n?n[0]:-1},first:function(){return this.get(0)},flatten:function(e){return St(this,vt(this,e,!1))},get:function(e,t){return e=m(this,e),e<0||this.size===1/0||void 0!==this.size&&e>this.size?t:this.find(function(t,n){return n===e},void 0,t)},has:function(e){return e=m(this,e),e>=0&&(void 0!==this.size?this.size===1/0||e0?"Unexpected "+(1===a.length?"property":"properties")+' "'+a.join('", "')+'" found in '+i+'. Expected to find one of the known reducer property names instead: "'+r.join('", "')+'". Unexpected properties will be ignored.':null},e.exports=t.default},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t,n){if(void 0===e)throw new Error('Reducer "'+t+'" returned undefined when handling "'+n.type+'" action. To ignore an action, you must explicitly return the previous state.');return null},e.exports=t.default},function(e,t){"use strict";function n(e,t){var r;return r=Array.isArray(e)?[]:{},t.push(e),Object.keys(e).forEach(function(i){var o=e[i];if("function"!=typeof o)return o&&"object"==typeof o?t.indexOf(e[i])===-1?void(r[i]=n(e[i],t.slice(0))):void(r[i]="[Circular]"):void(r[i]=o)}),r}e.exports=function(e){if("object"==typeof e){var t=n(e,[]);return"string"==typeof e.name&&(t.name=e.name),"string"==typeof e.message&&(t.message=e.message),"string"==typeof e.stack&&(t.stack=e.stack),t}return"function"==typeof e?"[Function: "+(e.name||"anonymous")+"]":e}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){return{type:p,payload:{action:t,error:(0,l.default)(e)}}}function o(e){return{type:f,payload:e}}function a(e){return{type:h,payload:e}}function s(e){return{type:d,payload:e}}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{type:m,payload:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.CLEAR=t.NEW_AUTH_ERR=t.NEW_SPEC_ERR=t.NEW_THROWN_ERR_BATCH=t.NEW_THROWN_ERR=void 0,t.newThrownErr=i,t.newThrownErrBatch=o,t.newSpecErr=a,
+t.newAuthErr=s,t.clear=u;var c=n(333),l=r(c),p=t.NEW_THROWN_ERR="err_new_thrown_err",f=t.NEW_THROWN_ERR_BATCH="err_new_thrown_err_batch",h=t.NEW_SPEC_ERR="err_new_spec_err",d=t.NEW_AUTH_ERR="err_new_auth_err",m=t.CLEAR="err_clear"},function(e,t){"use strict";function n(){var e={location:{},history:{},open:function(){},close:function(){}};if("undefined"==typeof window)return e;try{e=window;var t=["File","Blob","FormData"],n=!0,r=!1,i=void 0;try{for(var o,a=t[Symbol.iterator]();!(n=(o=a.next()).done);n=!0){var s=o.value;s in window&&(e[s]=window[s])}}catch(e){r=!0,i=e}finally{try{!n&&a.return&&a.return()}finally{if(r)throw i}}}catch(e){console.error(e)}return e}e.exports=n()},function(e,t,n){(function(e){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){return l(e)?q(e)?e.toObject():e:{}}function o(e){return e?e.toArray?e.toArray():u(e):[]}function a(e){return q(e)?e:l(e)?Array.isArray(e)?A.default.Seq(e).map(a).toList():A.default.Seq(e).map(a).toOrderedMap():e}function s(e,t){var n={};return Object.keys(e).filter(function(t){return"function"==typeof e[t]}).forEach(function(r){return n[r]=e[r].bind(null,t)}),n}function u(e){return Array.isArray(e)?e:[e]}function c(e){return"function"==typeof e}function l(e){return!!e&&"object"===("undefined"==typeof e?"undefined":E(e))}function p(e){return"function"==typeof e}function f(e){return Array.isArray(e)}function h(e,t){return Object.keys(e).reduce(function(n,r){return n[r]=t(e[r],r),n},{})}function d(e,t){return Object.keys(e).reduce(function(n,r){var i=t(e[r],r);return i&&"object"===("undefined"==typeof i?"undefined":E(i))&&Object.assign(n,i),n},{})}function m(e){return function(t){t.dispatch,t.getState;return function(t){return function(n){return"function"==typeof n?n(e()):t(n)}}}}function y(e){var t=e.keySeq();return t.contains(U)?U:t.filter(function(e){return"2"===(e+"")[0]}).sort().first()}function v(e,t){if(!A.default.Iterable.isIterable(e))return A.default.List();var n=e.getIn(Array.isArray(t)?t:[t]);return A.default.List.isList(n)?n:A.default.List()}function g(e){var t,n,r,i,o,a,s,u,c,l,p,f;for(l=/(>)(<)(\/*)/g,f=/[ ]*(.*)[ ]+\n/g,t=/(<.+>)(.+\n)/g,e=e.replace(/\r\n/g,"\n").replace(l,"$1\n$2$3").replace(f,"$1\n").replace(t,"$1\n$2"),r="",u=e.split("\n"),i=0,a="other",p={"single->single":0,"single->closing":-1,"single->opening":0,"single->other":0,"closing->single":0,"closing->closing":-1,"closing->opening":0,"closing->other":0,"opening->single":1,"opening->closing":0,"opening->opening":1,"opening->other":1,"other->single":0,"other->closing":-1,"other->opening":0,"other->other":0},n=function(e){var t,n,o,s,u,c;u={single:Boolean(e.match(/<.+\/>/)),closing:Boolean(e.match(/<\/.+>/)),opening:Boolean(e.match(/<[^!?].*>/))},s=function(){var e;e=[];for(n in u)c=u[n],c&&e.push(n);return e}()[0],s=void 0===s?"other":s,t=a+"->"+s,a=s,o="",i+=p[t],o=function(){var e,t,n,r;for(n=[],r=e=0,t=i;0<=t?et;r=0<=t?++e:--e)n.push(" ");return n}().join(""),"opening->closing"===t?r=r.substr(0,r.length-1)+e+"\n":r+=o+e+"\n"},o=0,s=u.length;ot)return e.textContent;var o=function(e){for(var t,o,a,s,u,c=e.textContent,l=0,p=c[0],f=1,h=e.innerHTML="",d=0;o=t,t=d<7&&"\\"==t?1:f;){if(f=p,p=c[++l],s=h.length>1,!f||d>8&&"\n"==f||[/\S/[i](f),1,1,!/[$\w]/[i](f),("/"==t||"\n"==t)&&s,'"'==t&&s,"'"==t&&s,c[l-4]+o+t=="-->",o+t=="*/"][d])for(h&&(e[r](u=n.createElement("span")).setAttribute("style",["color: #555; font-weight: bold;","","","color: #555;",""][d?d<3?2:d>6?4:d>3?3:+/^(a(bstract|lias|nd|rguments|rray|s(m|sert)?|uto)|b(ase|egin|ool(ean)?|reak|yte)|c(ase|atch|har|hecked|lass|lone|ompl|onst|ontinue)|de(bugger|cimal|clare|f(ault|er)?|init|l(egate|ete)?)|do|double|e(cho|ls?if|lse(if)?|nd|nsure|num|vent|x(cept|ec|p(licit|ort)|te(nds|nsion|rn)))|f(allthrough|alse|inal(ly)?|ixed|loat|or(each)?|riend|rom|unc(tion)?)|global|goto|guard|i(f|mp(lements|licit|ort)|n(it|clude(_once)?|line|out|stanceof|t(erface|ernal)?)?|s)|l(ambda|et|ock|ong)|m(icrolight|odule|utable)|NaN|n(amespace|ative|ext|ew|il|ot|ull)|o(bject|perator|r|ut|verride)|p(ackage|arams|rivate|rotected|rotocol|ublic)|r(aise|e(adonly|do|f|gister|peat|quire(_once)?|scue|strict|try|turn))|s(byte|ealed|elf|hort|igned|izeof|tatic|tring|truct|ubscript|uper|ynchronized|witch)|t(emplate|hen|his|hrows?|ransient|rue|ry|ype(alias|def|id|name|of))|u(n(checked|def(ined)?|ion|less|signed|til)|se|sing)|v(ar|irtual|oid|olatile)|w(char_t|hen|here|hile|ith)|xor|yield)$/[i](h):0]),u[r](n.createTextNode(h))),a=d&&d<7?d:a,h="",d=11;![1,/[\/{}[(\-+*=<>:;|\\.,?!&@~]/[i](f),/[\])]/[i](f),/[$\w]/[i](f),"/"==f&&a<2&&"<"!=t,'"'==f,"'"==f,f+p+c[l+1]+c[l+2]=="':null;var r=e.$$ref.match(/\S*\/(\S+)$/);e.xml.name=r[1]}return(0,L.memoizedCreateXMLExample)(e,n)}return JSON.stringify((0,L.memoizedSampleFromSchema)(e,n),null,2)},t.parseSeach=function(){var e={},t=window.location.search;if(""!=t){var n=t.substr(1).split("&");for(var r in n)r=n[r].split("="),e[decodeURIComponent(r[0])]=decodeURIComponent(r[1])}return e},t.btoa=function(t){var n=void 0;return n=t instanceof e?t:new e(t.toString(),"utf-8"),n.toString("base64")},t.sorters={operationsSorter:{alpha:function(e,t){return e.get("path").localeCompare(t.get("path"))},method:function(e,t){return e.get("method").localeCompare(t.get("method"))}}},t.buildFormData=function(e){var t=[];for(var n in e){var r=e[n];void 0!==r&&""!==r&&t.push([n,"=",encodeURIComponent(r).replace(/%20/g,"+")].join(""))}return t.join("&")},t.filterConfigs=function(e,t){var n=void 0,r={};for(n in e)t.indexOf(n)!==-1&&(r[n]=e[n]);return r}}).call(t,n(300).Buffer)},function(e,t,n){"use strict";var r=n(338);e.exports=function(e,t,n,i){var o=n?n.call(i,e,t):void 0;if(void 0!==o)return!!o;if(e===t)return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var a=r(e),s=r(t),u=a.length;if(u!==s.length)return!1;i=i||null;for(var c=Object.prototype.hasOwnProperty.bind(t),l=0;l-1&&e%1==0&&e-1&&e%1==0&&e<=v}function s(e){for(var t=c(e),n=t.length,r=n&&e.length,i=!!r&&a(r)&&(f(e)||p(e)),s=-1,u=[];++s0;++r-1&&e%1==0&&e<=c}function s(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function u(e){return!!e&&"object"==typeof e}var c=9007199254740991,l="[object Arguments]",p="[object Function]",f="[object GeneratorFunction]",h=Object.prototype,d=h.hasOwnProperty,m=h.toString,y=h.propertyIsEnumerable;e.exports=n},function(e,t){function n(e){return!!e&&"object"==typeof e}function r(e,t){var n=null==e?void 0:e[t];return s(n)?n:void 0}function i(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=v}function o(e){return a(e)&&d.call(e)==c}function a(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function s(e){return null!=e&&(o(e)?m.test(f.call(e)):n(e)&&l.test(e))}var u="[object Array]",c="[object Function]",l=/^\[object .+?Constructor\]$/,p=Object.prototype,f=Function.prototype.toString,h=p.hasOwnProperty,d=p.toString,m=RegExp("^"+f.call(h).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),y=r(Array,"isArray"),v=9007199254740991,g=y||function(e){return n(e)&&i(e.length)&&d.call(e)==u};e.exports=g},function(e,t,n){var r=n(343),i=n(357),o=i(function(e,t,n){return t=t.toLowerCase(),e+(n?r(t):t)});e.exports=o},function(e,t,n){function r(e){return o(i(e).toLowerCase())}var i=n(344),o=n(349);e.exports=r},function(e,t,n){function r(e){return null==e?"":i(e)}var i=n(345);e.exports=r},function(e,t,n){function r(e){if("string"==typeof e)return e;if(a(e))return o(e,r)+"";if(s(e))return l?l.call(e):"";var t=e+"";return"0"==t&&1/e==-u?"-0":t}var i=n(309),o=n(346),a=n(347),s=n(348),u=1/0,c=i?i.prototype:void 0,l=c?c.toString:void 0;e.exports=r},function(e,t){function n(e,t){for(var n=-1,r=null==e?0:e.length,i=Array(r);++n=r?e:i(e,t,n)}var i=n(352);e.exports=r},function(e,t){function n(e,t,n){var r=-1,i=e.length;t<0&&(t=-t>i?0:i+t),n=n>i?i:n,n<0&&(n+=i),i=t>n?0:n-t>>>0,t>>>=0;for(var o=Array(i);++rf))return!1;var d=l.get(e);if(d&&l.get(t))return d==t;var m=-1,y=!0,v=n&u?new i:void 0;for(l.set(e,t),l.set(t,e);++m-1&&e%1==0&&e-1&&e%1==0&&e<=r}var r=9007199254740991;e.exports=n},function(e,t){function n(e){return function(t){return e(t)}}e.exports=n},function(e,t,n){(function(e){var r=n(311),i="object"==typeof t&&t&&!t.nodeType&&t,o=i&&"object"==typeof e&&e&&!e.nodeType&&e,a=o&&o.exports===i,s=a&&r.process,u=function(){try{return s&&s.binding&&s.binding("util")}catch(e){}}();e.exports=u}).call(t,n(319)(e))},[1462,436,437],function(e,t){function n(e){var t=e&&e.constructor,n="function"==typeof t&&t.prototype||r;return e===n}var r=Object.prototype;e.exports=n},[1463,315],[1464,374,432],function(e,t,n){var r=n(440),i=n(392),o=n(441),a=n(442),s=n(443),u=n(308),c=n(378),l="[object Map]",p="[object Object]",f="[object Promise]",h="[object Set]",d="[object WeakMap]",m="[object DataView]",y=c(r),v=c(i),g=c(o),_=c(a),b=c(s),w=u;(r&&w(new r(new ArrayBuffer(1)))!=m||i&&w(new i)!=l||o&&w(o.resolve())!=f||a&&w(new a)!=h||s&&w(new s)!=d)&&(w=function(e){var t=u(e),n=t==p?e.constructor:void 0,r=n?c(n):"";if(r)switch(r){case y:return m;case v:return l;case g:return f;case _:return h;case b:return d}return t}),e.exports=w},[1465,372,310],[1466,372,310],[1467,372,310],[1468,372,310],function(e,t,n){function r(e){for(var t=o(e),n=t.length;n--;){var r=t[n],a=e[r];t[n]=[r,a,i(a)]}return t}var i=n(445),o=n(422);e.exports=r},function(e,t,n){function r(e){return e===e&&!i(e)}var i=n(375);e.exports=r},function(e,t){function n(e,t){return function(n){return null!=n&&(n[e]===t&&(void 0!==t||e in Object(n)))}}e.exports=n},function(e,t,n){function r(e,t){return s(e)&&u(t)?c(l(e),t):function(n){var r=o(n,e);return void 0===r&&r===t?a(n,e):i(t,r,p|f)}}var i=n(410),o=n(448),a=n(455),s=n(451),u=n(445),c=n(446),l=n(454),p=1,f=2;e.exports=r},[1469,449],function(e,t,n){function r(e,t){t=i(t,e);for(var n=0,r=t.length;null!=e&&n1&&void 0!==arguments[1]?arguments[1]:{},r=(0,o.objectify)(t),i=r.type,a=r.example,s=r.properties,u=r.additionalProperties,c=r.items,l=n.includeReadOnly;if(void 0!==a)return a;if(!i)if(s)i="object";else{if(!c)return;i="array"}if("object"===i){var f=(0,o.objectify)(s),h={};for(var d in f)f[d].readOnly&&!l||(h[d]=e(f[d],{includeReadOnly:l}));if(u===!0)h.additionalProp1={};else if(u)for(var m=(0,o.objectify)(u),y=e(m,{includeReadOnly:l}),v=1;v<4;v++)h["additionalProp"+v]=y;return h}return"array"===i?[e(c,{includeReadOnly:l})]:t.enum?t.default?t.default:(0,o.normalizeArray)(t.enum)[0]:p(t)},h=(t.inferSchema=function(e){return e.schema&&(e=e.schema),e.properties&&(e.type="object"),e},t.sampleXmlFromSchema=function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=(0,o.objectify)(t),i=r.type,a=r.properties,s=r.additionalProperties,u=r.items,c=r.example,l=n.includeReadOnly,f=r.default,h={},d={},m=t.xml,y=m.name,v=m.prefix,g=m.namespace,_=r.enum,b=void 0,w=void 0;if(!i)if(a||s)i="object";else{if(!u)return;i="array"}if(y=y||"notagname",b=(v?v+":":"")+y,g){var x=v?"xmlns:"+v:"xmlns";d[x]=g}if("array"===i&&u){if(u.xml=u.xml||m||{},u.xml.name=u.xml.name||m.name,m.wrapped)return h[b]=[],Array.isArray(c)?c.forEach(function(t){u.example=t,h[b].push(e(u,n))}):Array.isArray(f)?f.forEach(function(t){u.default=t,h[b].push(e(u,n))}):h[b]=[e(u,n)],d&&h[b].push({_attr:d}),h;var k=[];return Array.isArray(c)?(c.forEach(function(t){u.example=t,k.push(e(u,n))}),k):Array.isArray(f)?(f.forEach(function(t){u.default=t,k.push(e(u,n))}),k):e(u,n)}if("object"===i){var S=(0,o.objectify)(a);h[b]=[],c=c||{};for(var E in S)if(!S[E].readOnly||l)if(S[E].xml=S[E].xml||{},S[E].xml.attribute){var C=Array.isArray(S[E].enum)&&S[E].enum[0],A=S[E].example,T=S[E].default;d[S[E].xml.name||E]=void 0!==A&&A||void 0!==c[E]&&c[E]||void 0!==T&&T||C||p(S[E])}else{S[E].xml.name=S[E].xml.name||E,S[E].example=void 0!==S[E].example?S[E].example:c[E];var O=e(S[E]);Array.isArray(O)?h[b]=h[b].concat(O):h[b].push(O)}return s===!0?h[b].push({additionalProp:"Anything can be here"}):s&&h[b].push({additionalProp:p(s)}),d&&h[b].push({_attr:d}),h}return w=void 0!==c?c:void 0!==f?f:Array.isArray(_)?_[0]:p(t),h[b]=d?[{_attr:d},w]:w,h});t.memoizedCreateXMLExample=(0,c.default)(i),t.memoizedSampleFromSchema=(0,c.default)(f)},function(e,t,n){(function(t){function r(e,n){function r(e){y?t.nextTick(e):e()}function i(e,t){if(void 0!==t&&(h+=t),e&&!d&&(f=f||new l,d=!0),e&&d){var n=h;r(function(){f.emit("data",n)}),h=""}}function o(e,t){s(i,a(e,m,m?1:0),t)}function u(){if(f){var e=h;r(function(){f.emit("data",e),f.emit("end"),f.readable=!1,f.emit("close")})}}function c(e){var t=e.encoding||"UTF-8",n={version:"1.0",encoding:t};e.standalone&&(n.standalone=e.standalone),o({"?xml":{_attr:n}}),h=h.replace("/>","?>")}"object"!=typeof n&&(n={indent:n});var f=n.stream?new l:null,h="",d=!1,m=n.indent?n.indent===!0?p:n.indent:"",y=!0;return r(function(){y=!1}),n.declaration&&c(n.declaration),e&&e.forEach?e.forEach(function(t,n){var r;n+1===e.length&&(r=u),o(t,r)}):o(e,u),f?(f.readable=!0,f):h}function i(){var e=Array.prototype.slice.call(arguments),t={_elem:a(e)};return t.push=function(e){if(!this.append)throw new Error("not assigned to a parent!");var t=this,n=this._elem.indent;s(this.append,a(e,n,this._elem.icount+(n?1:0)),function(){t.append(!0)})},t.close=function(e){void 0!==e&&this.push(e),this.end&&this.end()},t}function o(e,t){return new Array(t||0).join(e||"")}function a(e,t,n){function r(e){var t=Object.keys(e);t.forEach(function(t){d.push(u(t,e[t]))})}n=n||0;var i,s=o(t,n),l=e,p=!1;if("object"==typeof e){var f=Object.keys(e);if(i=f[0],l=e[i],l&&l._elem)return l._elem.name=i,l._elem.icount=n,l._elem.indent=t,l._elem.indents=s,l._elem.interrupt=l,l._elem}var h,d=[],m=[];switch(typeof l){case"object":if(null===l)break;l._attr&&r(l._attr),l._cdata&&m.push(("/g,"]]]]>")+"]]>"),l.forEach&&(h=!1,m.push(""),l.forEach(function(e){if("object"==typeof e){var i=Object.keys(e)[0];"_attr"==i?r(e._attr):m.push(a(e,t,n+1))}else m.pop(),h=!0,m.push(c(e))}),h||m.push(""));break;default:m.push(c(l))}return{name:i,interrupt:p,attributes:d,content:m,icount:n,indents:s,indent:t}}function s(e,t,n){function r(){for(;t.content.length;){var r=t.content.shift();if(void 0!==r){if(i(r))return;s(e,r)}}e(!1,(o>1?t.indents:"")+(t.name?""+t.name+">":"")+(t.indent&&!n?"\n":"")),n&&n()}function i(t){return!!t.interrupt&&(t.interrupt.append=e,t.interrupt.end=r,t.interrupt=!1,e(!0),!0)}if("object"!=typeof t)return e(!1,t);var o=t.interrupt?1:t.content.length;return e(!1,t.indents+(t.name?"<"+t.name:"")+(t.attributes.length?" "+t.attributes.join(" "):"")+(o?t.name?">":"":t.name?"/>":"")+(t.indent&&o>1?"\n":"")),o?void(i(t)||r()):e(!1,t.indent?"\n":"")}function u(e,t){return e+'="'+c(t)+'"'}var c=n(471),l=n(472).Stream,p=" ";e.exports=r,e.exports.element=e.exports.Element=i}).call(t,n(294))},function(e,t){function n(e){return e&&e.replace?e.replace(/([&"<>'])/g,function(e,t){return r[t]}):e}var r={"&":"&",'"':""","'":"'","<":"<",">":">"};e.exports=n},function(e,t,n){function r(){i.call(this)}e.exports=r;var i=n(473).EventEmitter,o=n(474);o(r,i),r.Readable=n(475),r.Writable=n(490),r.Duplex=n(491),r.Transform=n(492),r.PassThrough=n(493),r.Stream=r,r.prototype.pipe=function(e,t){function n(t){e.writable&&!1===e.write(t)&&c.pause&&c.pause()}function r(){c.readable&&c.resume&&c.resume()}function o(){l||(l=!0,e.end())}function a(){l||(l=!0,"function"==typeof e.destroy&&e.destroy())}function s(e){if(u(),0===i.listenerCount(this,"error"))throw e}function u(){c.removeListener("data",n),e.removeListener("drain",r),c.removeListener("end",o),c.removeListener("close",a),c.removeListener("error",s),e.removeListener("error",s),c.removeListener("end",u),c.removeListener("close",u),e.removeListener("close",u)}var c=this;c.on("data",n),e.on("drain",r),e._isStdio||t&&t.end===!1||(c.on("end",o),c.on("close",a));var l=!1;return c.on("error",s),e.on("error",s),c.on("end",u),c.on("close",u),e.on("close",u),e.emit("pipe",c),e}},function(e,t){function n(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function i(e){return"number"==typeof e}function o(e){return"object"==typeof e&&null!==e}function a(e){return void 0===e}e.exports=n,n.EventEmitter=n,n.prototype._events=void 0,n.prototype._maxListeners=void 0,n.defaultMaxListeners=10,n.prototype.setMaxListeners=function(e){if(!i(e)||e<0||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},n.prototype.emit=function(e){var t,n,i,s,u,c;if(this._events||(this._events={}),"error"===e&&(!this._events.error||o(this._events.error)&&!this._events.error.length)){if(t=arguments[1],t instanceof Error)throw t;var l=new Error('Uncaught, unspecified "error" event. ('+t+")");throw l.context=t,l}if(n=this._events[e],a(n))return!1;if(r(n))switch(arguments.length){case 1:n.call(this);break;case 2:n.call(this,arguments[1]);break;case 3:n.call(this,arguments[1],arguments[2]);break;default:s=Array.prototype.slice.call(arguments,1),n.apply(this,s)}else if(o(n))for(s=Array.prototype.slice.call(arguments,1),c=n.slice(),i=c.length,u=0;u0&&this._events[e].length>i&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace())),this},n.prototype.on=n.prototype.addListener,n.prototype.once=function(e,t){function n(){this.removeListener(e,n),i||(i=!0,t.apply(this,arguments))}if(!r(t))throw TypeError("listener must be a function");var i=!1;return n.listener=t,this.on(e,n),this},n.prototype.removeListener=function(e,t){var n,i,a,s;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(n=this._events[e],a=n.length,i=-1,n===t||r(n.listener)&&n.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(o(n)){for(s=a;s-- >0;)if(n[s]===t||n[s].listener&&n[s].listener===t){i=s;break}if(i<0)return this;1===n.length?(n.length=0,delete this._events[e]):n.splice(i,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},n.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(n=this._events[e],r(n))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},n.prototype.listeners=function(e){var t;return t=this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},n.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},n.listenerCount=function(e,t){return e.listenerCount(t)}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){(function(r){var i=function(){try{return n(472)}catch(e){}}();t=e.exports=n(476),t.Stream=i||t,t.Readable=t,t.Writable=n(483),t.Duplex=n(482),t.Transform=n(488),t.PassThrough=n(489),!r.browser&&"disable"==={NODE_ENV:"production",WEBPACK_INLINE_STYLES:!0}.READABLE_STREAM&&i&&(e.exports=i)}).call(t,n(294))},function(e,t,n){(function(t){"use strict";function r(e,t,n){return"function"==typeof e.prependListener?e.prependListener(t,n):void(e._events&&e._events[t]?M(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n))}function i(e,t){O=O||n(482),e=e||{},this.objectMode=!!e.objectMode,t instanceof O&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var r=e.highWaterMark,i=this.objectMode?16:16384;this.highWaterMark=r||0===r?r:i,this.highWaterMark=~~this.highWaterMark,this.buffer=new L,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.ranOut=!1,this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(z||(z=n(487).StringDecoder),this.decoder=new z(e.encoding),this.encoding=e.encoding)}function o(e){return O=O||n(482),this instanceof o?(this._readableState=new i(e,this),this.readable=!0,e&&"function"==typeof e.read&&(this._read=e.read),void P.call(this)):new o(e)}function a(e,t,n,r,i){var o=l(t,n);if(o)e.emit("error",o);else if(null===n)t.reading=!1,p(e,t);else if(t.objectMode||n&&n.length>0)if(t.ended&&!i){var a=new Error("stream.push() after EOF");e.emit("error",a)}else if(t.endEmitted&&i){var u=new Error("stream.unshift() after end event");e.emit("error",u)}else{var c;!t.decoder||i||r||(n=t.decoder.write(n),c=!t.objectMode&&0===n.length),i||(t.reading=!1),c||(t.flowing&&0===t.length&&!t.sync?(e.emit("data",n),e.read(0)):(t.length+=t.objectMode?1:n.length,i?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&f(e))),d(e,t)}else i||(t.reading=!1);return s(t)}function s(e){return!e.ended&&(e.needReadable||e.length=U?e=U:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}function c(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!==e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=u(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function l(e,t){var n=null;return j.isBuffer(t)||"string"==typeof t||null===t||void 0===t||e.objectMode||(n=new TypeError("Invalid non-string/buffer chunk")),n}function p(e,t){if(!t.ended){if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,f(e)}}function f(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(N("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?D(h,e):h(e))}function h(e){N("emit readable"),e.emit("readable"),b(e)}function d(e,t){t.readingMore||(t.readingMore=!0,D(m,e,t))}function m(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=x(e,t.buffer,t.decoder),n}function x(e,t,n){var r;return eo.length?o.length:e;if(i+=a===o.length?o:o.slice(0,e),e-=a,0===e){a===o.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=o.slice(a));break}++r}return t.length-=r,i}function S(e,t){var n=R.allocUnsafe(e),r=t.head,i=1;for(r.data.copy(n),e-=r.data.length;r=r.next;){var o=r.data,a=e>o.length?o.length:e;if(o.copy(n,n.length-e,0,a),e-=a,0===e){a===o.length?(++i,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=o.slice(a));break}++i}return t.length-=i,n}function E(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,D(C,t,e))}function C(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function A(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return N("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?E(this):f(this),null;if(e=c(e,t),0===e&&t.ended)return 0===t.length&&E(this),null;var r=t.needReadable;N("need readable",r),(0===t.length||t.length-e0?w(e,t):null,null===i?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&E(this)),null!==i&&this.emit("data",i),i},o.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},o.prototype.pipe=function(e,n){function i(e){N("onunpipe"),e===f&&a()}function o(){N("onend"),e.end()}function a(){N("cleanup"),e.removeListener("close",c),e.removeListener("finish",l),e.removeListener("drain",v),e.removeListener("error",u),e.removeListener("unpipe",i),f.removeListener("end",o),f.removeListener("end",a),f.removeListener("data",s),g=!0,!h.awaitDrain||e._writableState&&!e._writableState.needDrain||v()}function s(t){N("ondata"),_=!1;var n=e.write(t);!1!==n||_||((1===h.pipesCount&&h.pipes===e||h.pipesCount>1&&T(h.pipes,e)!==-1)&&!g&&(N("false write response, pause",f._readableState.awaitDrain),f._readableState.awaitDrain++,_=!0),f.pause())}function u(t){N("onerror",t),p(),e.removeListener("error",u),0===I(e,"error")&&e.emit("error",t)}function c(){e.removeListener("finish",l),p()}function l(){N("onfinish"),e.removeListener("close",c),p()}function p(){N("unpipe"),f.unpipe(e)}var f=this,h=this._readableState;switch(h.pipesCount){case 0:h.pipes=e;break;case 1:h.pipes=[h.pipes,e];break;default:h.pipes.push(e)}h.pipesCount+=1,N("pipe count=%d opts=%j",h.pipesCount,n);var d=(!n||n.end!==!1)&&e!==t.stdout&&e!==t.stderr,m=d?o:a;h.endEmitted?D(m):f.once("end",m),e.on("unpipe",i);var v=y(f);e.on("drain",v);var g=!1,_=!1;return f.on("data",s),r(e,"error",u),e.once("close",c),e.once("finish",l),e.emit("pipe",f),h.flowing||(N("pipe resume"),f.resume()),e},o.prototype.unpipe=function(e){var t=this._readableState;if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this),this);if(!e){var n=t.pipes,r=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;ia)throw new RangeError("size is too large");var r=n,o=t;void 0===o&&(r=void 0,o=0);var s=new i(e);if("string"==typeof o)for(var u=new i(o,r),c=u.length,l=-1;++la)throw new RangeError("size is too large");return new i(e)},t.from=function(t,n,r){if("function"==typeof i.from&&(!e.Uint8Array||Uint8Array.from!==i.from))return i.from(t,n,r);if("number"==typeof t)throw new TypeError('"value" argument must not be a number');if("string"==typeof t)return new i(t,n);if("undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer){var o=n;if(1===arguments.length)return new i(t);"undefined"==typeof o&&(o=0);var a=r;if("undefined"==typeof a&&(a=t.byteLength-o),o>=t.byteLength)throw new RangeError("'offset' is out of bounds");if(a>t.byteLength-o)throw new RangeError("'length' is out of bounds");return new i(t.slice(o,o+a))}if(i.isBuffer(t)){var s=new i(t.length);return t.copy(s,0,0,t.length),s}if(t){if(Array.isArray(t)||"undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return new i(t);if("Buffer"===t.type&&Array.isArray(t.data))return new i(t.data)}throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")},t.allocUnsafeSlow=function(e){if("function"==typeof i.allocUnsafeSlow)return i.allocUnsafeSlow(e);if("number"!=typeof e)throw new TypeError("size must be a number");if(e>=a)throw new RangeError("size is too large");return new o(e)}}).call(t,function(){return this}())},function(e,t,n){(function(e){function n(e){return Array.isArray?Array.isArray(e):"[object Array]"===y(e)}function r(e){return"boolean"==typeof e}function i(e){return null===e}function o(e){return null==e}function a(e){return"number"==typeof e}function s(e){return"string"==typeof e}function u(e){return"symbol"==typeof e}function c(e){return void 0===e}function l(e){return"[object RegExp]"===y(e)}function p(e){return"object"==typeof e&&null!==e}function f(e){return"[object Date]"===y(e)}function h(e){return"[object Error]"===y(e)||e instanceof Error}function d(e){return"function"==typeof e}function m(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function y(e){return Object.prototype.toString.call(e)}t.isArray=n,t.isBoolean=r,t.isNull=i,t.isNullOrUndefined=o,t.isNumber=a,t.isString=s,t.isSymbol=u,t.isUndefined=c,t.isRegExp=l,t.isObject=p,t.isDate=f,t.isError=h,t.isFunction=d,t.isPrimitive=m,t.isBuffer=e.isBuffer}).call(t,n(300).Buffer)},function(e,t){},function(e,t,n){"use strict";function r(){this.head=null,this.tail=null,this.length=0}var i=(n(300).Buffer,n(478));e.exports=r,r.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},r.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},r.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},r.prototype.clear=function(){this.head=this.tail=null,this.length=0},r.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},r.prototype.concat=function(e){if(0===this.length)return i.alloc(0);if(1===this.length)return this.head.data;for(var t=i.allocUnsafe(e>>>0),n=this.head,r=0;n;)n.data.copy(t,r),r+=n.data.length,n=n.next;return t}},function(e,t,n){"use strict";function r(e){return this instanceof r?(c.call(this,e),l.call(this,e),e&&e.readable===!1&&(this.readable=!1),e&&e.writable===!1&&(this.writable=!1),this.allowHalfOpen=!0,e&&e.allowHalfOpen===!1&&(this.allowHalfOpen=!1),void this.once("end",i)):new r(e)}function i(){this.allowHalfOpen||this._writableState.ended||s(o,this)}function o(e){e.end()}var a=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=r;var s=n(477),u=n(479);u.inherits=n(474);var c=n(476),l=n(483);u.inherits(r,c);for(var p=a(l.prototype),f=0;f-1?r:E;s.WritableState=a;var A=n(479);A.inherits=n(474);var T,O={deprecate:n(486)};!function(){try{T=n(472)}catch(e){}finally{T||(T=n(473).EventEmitter)}}();var D=n(300).Buffer,M=n(478);A.inherits(s,T),a.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(a.prototype,"buffer",{get:O.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.")})}catch(e){}}();var P;"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(P=Function.prototype[Symbol.hasInstance],Object.defineProperty(s,Symbol.hasInstance,{value:function(e){return!!P.call(this,e)||e&&e._writableState instanceof a}})):P=function(e){return e instanceof this},s.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},s.prototype.write=function(e,t,n){var r=this._writableState,o=!1,a=D.isBuffer(e);return"function"==typeof t&&(n=t,t=null),a?t="buffer":t||(t=r.defaultEncoding),"function"!=typeof n&&(n=i),r.ended?u(this,n):(a||c(this,r,e,n))&&(r.pendingcb++,o=p(this,r,a,e,t,n)),o},s.prototype.cork=function(){var e=this._writableState;e.corked++},s.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||g(this,e))},s.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,
+this},s.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},s.prototype._writev=null,s.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!==e&&void 0!==e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||x(this,r,n)}}).call(t,n(294),n(484).setImmediate)},function(e,t,n){function r(e,t){this._id=e,this._clearFn=t}var i=Function.prototype.apply;t.setTimeout=function(){return new r(i.call(setTimeout,window,arguments),clearTimeout)},t.setInterval=function(){return new r(i.call(setInterval,window,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},r.prototype.unref=r.prototype.ref=function(){},r.prototype.close=function(){this._clearFn.call(window,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(485),t.setImmediate=setImmediate,t.clearImmediate=clearImmediate},function(e,t,n){(function(e,t){!function(e,n){"use strict";function r(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,n),this.charReceived+=n,this.charReceived=55296&&r<=56319)){if(this.charReceived=this.charLength=0,0===e.length)return t;break}this.charLength+=this.surrogateSize,t=""}this.detectIncompleteChar(e);var i=e.length;this.charLength&&(e.copy(this.charBuffer,0,e.length-this.charReceived,i),i-=this.charReceived),t+=e.toString(this.encoding,0,i);var i=t.length-1,r=t.charCodeAt(i);if(r>=55296&&r<=56319){var o=this.surrogateSize;return this.charLength+=o,this.charReceived+=o,this.charBuffer.copy(this.charBuffer,o,0,o),e.copy(this.charBuffer,0,0,o),t.substring(0,i)}return t},c.prototype.detectIncompleteChar=function(e){for(var t=e.length>=3?3:e.length;t>0;t--){var n=e[e.length-t];if(1==t&&n>>5==6){this.charLength=2;break}if(t<=2&&n>>4==14){this.charLength=3;break}if(t<=3&&n>>3==30){this.charLength=4;break}}this.charReceived=t},c.prototype.end=function(e){var t="";if(e&&e.length&&(t=this.write(e)),this.charReceived){var n=this.charReceived,r=this.charBuffer,i=this.encoding;t+=r.slice(0,n).toString(i)}return t}},function(e,t,n){"use strict";function r(e){this.afterTransform=function(t,n){return i(e,t,n)},this.needTransform=!1,this.transforming=!1,this.writecb=null,this.writechunk=null,this.writeencoding=null}function i(e,t,n){var r=e._transformState;r.transforming=!1;var i=r.writecb;if(!i)return e.emit("error",new Error("no writecb in Transform class"));r.writechunk=null,r.writecb=null,null!==n&&void 0!==n&&e.push(n),i(t);var o=e._readableState;o.reading=!1,(o.needReadable||o.length1&&(a.normalizer=n(540)(t)):t===!1?a.normalizer=n(541)():1===t?a.normalizer=n(543)():a.normalizer=n(544)(t))),a.async&&n(545),a.promise&&n(548),a.dispose&&n(550),a.maxAge&&n(551),a.max&&n(554),a.refCounter&&n(556),o(e,a)}},function(e,t){"use strict";var n=Array.prototype.forEach,r=Object.create,i=function(e,t){var n;for(n in e)t[n]=e[n]};e.exports=function(e){var t=r(null);return n.call(arguments,function(e){null!=e&&i(Object(e),t)}),t}},function(e,t,n){"use strict";var r=n(497);e.exports=function(e,t,n){var i;return isNaN(e)?(i=t,i>=0?n&&i?i-1:i:1):e!==!1&&r(e)}},function(e,t,n){"use strict";var r=n(498),i=Math.max;e.exports=function(e){return i(0,r(e))}},function(e,t,n){"use strict";var r=n(499),i=Math.abs,o=Math.floor;e.exports=function(e){return isNaN(e)?0:(e=Number(e),0!==e&&isFinite(e)?r(e)*o(i(e)):e)}},function(e,t,n){"use strict";e.exports=n(500)()?Math.sign:n(501)},function(e,t){"use strict";e.exports=function(){var e=Math.sign;return"function"==typeof e&&(1===e(10)&&e(-20)===-1)}},function(e,t){"use strict";e.exports=function(e){return e=Number(e),isNaN(e)||0===e?e:e>0?1:-1}},function(e,t,n){"use strict";var r=n(503),i=n(504),o=n(507),a=n(508),s=n(496),u=Object.prototype.hasOwnProperty;e.exports=function e(t){var n,c,l;if(r(t),n=Object(arguments[1]),n.async&&n.promise)throw new Error("Options 'async' and 'promise' cannot be used together");return u.call(t,"__memoized__")&&!n.force?t:(c=s(n.length,t.length,n.async&&o.async),l=a(t,c,n),i(o,function(e,t){n[t]&&e(n[t],l,n)}),e.__profiler__&&e.__profiler__(l),l.updateEnv(),l.memoized)}},function(e,t){"use strict";e.exports=function(e){if("function"!=typeof e)throw new TypeError(e+" is not a function");return e}},function(e,t,n){"use strict";e.exports=n(505)("forEach")},function(e,t,n){"use strict";var r=n(503),i=n(506),o=Function.prototype.bind,a=Function.prototype.call,s=Object.keys,u=Object.prototype.propertyIsEnumerable;e.exports=function(e,t){return function(n,c){var l,p=arguments[2],f=arguments[3];return n=Object(i(n)),r(c),l=s(n),f&&l.sort("function"==typeof f?o.call(f,n):void 0),"function"!=typeof e&&(e=l[e]),a.call(e,l,function(e,r){return u.call(n,e)?a.call(c,p,n[e],e,n,r):t})}}},function(e,t){"use strict";e.exports=function(e){if(null==e)throw new TypeError("Cannot use null or undefined");return e}},function(e,t){"use strict"},function(e,t,n){"use strict";var r=n(509),i=n(516),o=n(518),a=n(523).methods,s=n(524),u=n(538),c=Function.prototype.apply,l=Function.prototype.call,p=Object.create,f=Object.prototype.hasOwnProperty,h=Object.defineProperties,d=a.on,m=a.emit;e.exports=function(e,t,n){var a,y,v,g,_,b,w,x,k,S,E,C,A,T=p(null);return y=t!==!1?t:isNaN(e.length)?1:e.length,n.normalizer&&(x=u(n.normalizer),v=x.get,g=x.set,_=x.delete,b=x.clear),null!=n.resolvers&&(A=s(n.resolvers)),C=v?i(function(t){var n,i,o=arguments;if(A&&(o=A(o)),n=v(o),null!==n&&f.call(T,n))return k&&a.emit("get",n,o,this),T[n];if(i=1===o.length?l.call(e,this,o[0]):c.call(e,this,o),null===n){if(n=v(o),null!==n)throw r("Circular invocation","CIRCULAR_INVOCATION");n=g(o)}else if(f.call(T,n))throw r("Circular invocation","CIRCULAR_INVOCATION");return T[n]=i,S&&a.emit("set",n,null,i),i},y):0===t?function(){var t;if(f.call(T,"data"))return k&&a.emit("get","data",arguments,this),T.data;if(t=arguments.length?c.call(e,this,arguments):l.call(e,this),f.call(T,"data"))throw r("Circular invocation","CIRCULAR_INVOCATION");return T.data=t,S&&a.emit("set","data",null,t),t}:function(t){var n,i,o=arguments;if(A&&(o=A(arguments)),i=String(o[0]),f.call(T,i))return k&&a.emit("get",i,o,this),T[i];if(n=1===o.length?l.call(e,this,o[0]):c.call(e,this,o),f.call(T,i))throw r("Circular invocation","CIRCULAR_INVOCATION");return T[i]=n,S&&a.emit("set",i,null,n),n},a={original:e,memoized:C,get:function(e){return A&&(e=A(e)),v?v(e):String(e[0])},has:function(e){return f.call(T,e)},delete:function(e){var t;f.call(T,e)&&(_&&_(e),t=T[e],delete T[e],E&&a.emit("delete",e,t))},clear:function(){var e=T;b&&b(),T=p(null),a.emit("clear",e)},on:function(e,t){return"get"===e?k=!0:"set"===e?S=!0:"delete"===e&&(E=!0),d.call(this,e,t)},emit:m,updateEnv:function(){e=a.original}},w=v?i(function(e){var t,n=arguments;A&&(n=A(n)),t=v(n),null!==t&&a.delete(t)},y):0===t?function(){return a.delete("data")}:function(e){return A&&(e=A(arguments)[0]),a.delete(e)},h(C,{__memoized__:o(!0),delete:o(w),clear:o(a.clear)}),a}},function(e,t,n){"use strict";var r=n(510),i=Error.captureStackTrace;t=e.exports=function(e){var n=new Error(e),o=arguments[1],a=arguments[2];return null==a&&o&&"object"==typeof o&&(a=o,o=null),null!=a&&r(n,a),null!=o&&(n.code=String(o)),i&&i(n,t),n}},function(e,t,n){"use strict";e.exports=n(511)()?Object.assign:n(512)},function(e,t){"use strict";e.exports=function(){var e,t=Object.assign;return"function"==typeof t&&(e={foo:"raz"},t(e,{bar:"dwa"},{trzy:"trzy"}),e.foo+e.bar+e.trzy==="razdwatrzy")}},function(e,t,n){"use strict";var r=n(513),i=n(506),o=Math.max;e.exports=function(e,t){var n,a,s,u=o(arguments.length,2);for(e=Object(i(e)),s=function(r){try{e[r]=t[r]}catch(e){n||(n=e)}},a=1;a-1}},function(e,t,n){"use strict";var r,i,o,a,s,u,c,l=n(518),p=n(503),f=Function.prototype.apply,h=Function.prototype.call,d=Object.create,m=Object.defineProperty,y=Object.defineProperties,v=Object.prototype.hasOwnProperty,g={configurable:!0,enumerable:!1,writable:!0};r=function(e,t){var n;return p(t),v.call(this,"__ee__")?n=this.__ee__:(n=g.value=d(null),m(this,"__ee__",g),g.value=null),n[e]?"object"==typeof n[e]?n[e].push(t):n[e]=[n[e],t]:n[e]=t,this},i=function(e,t){var n,i;return p(t),i=this,r.call(this,e,n=function(){o.call(i,e,n),f.call(t,this,arguments)}),n.__eeOnceListener__=t,this},o=function(e,t){var n,r,i,o;if(p(t),!v.call(this,"__ee__"))return this;if(n=this.__ee__,!n[e])return this;if(r=n[e],"object"==typeof r)for(o=0;i=r[o];++o)i!==t&&i.__eeOnceListener__!==t||(2===r.length?n[e]=r[o?0:1]:r.splice(o,1));else r!==t&&r.__eeOnceListener__!==t||delete n[e];return this},a=function(e){var t,n,r,i,o;if(v.call(this,"__ee__")&&(i=this.__ee__[e]))if("object"==typeof i){for(n=arguments.length,o=new Array(n-1),t=1;t=55296&&v<=56319&&(w+=e[++n])),w=x?p.call(x,k,w,d):w,t?(f.value=w,h(m,d,f)):m[d]=w,++d;y=d}if(void 0===y)for(y=a(e.length),t&&(m=new t(y)),n=0;n=0?u(c):r(this.length)-u(s(c)),t=c;ti)throw new TypeError(e+" exceeds maximum possible timeout");return e}},function(e,t){"use strict";e.exports=2147483647},function(e,t,n){"use strict";var r=n(497),i=n(555),o=n(507);o.max=function(e,t,n){var a,s,u;e=r(e),e&&(s=i(e),a=n.async&&o.async||n.promise&&o.promise?"async":"",t.on("set"+a,u=function(e){e=s.hit(e),void 0!==e&&t.delete(e)}),t.on("get"+a,u),t.on("delete"+a,s.delete),t.on("clear"+a,s.clear))}},function(e,t,n){"use strict";var r=n(497),i=Object.create,o=Object.prototype.hasOwnProperty;e.exports=function(e){var t,n=0,a=1,s=i(null),u=i(null),c=0;return e=r(e),{hit:function(r){var i=u[r],l=++c;if(s[l]=r,u[r]=l,!i){if(++n,n<=e)return;return r=s[a],t(r),r}if(delete s[i],a===i)for(;!o.call(s,++a);)continue},delete:t=function(e){var t=u[e];if(t&&(delete s[t],delete u[e],--n,a===t)){if(!n)return c=0,void(a=1);for(;!o.call(s,++a);)continue}},clear:function(){n=0,a=1,s=i(null),u=i(null),c=0}}}},function(e,t,n){"use strict";var r=n(518),i=n(507),o=Object.create,a=Object.defineProperties;i.refCounter=function(e,t,n){var s,u;s=o(null),u=n.async&&i.async||n.promise&&i.promise?"async":"",t.on("set"+u,function(e,t){s[e]=t||1}),t.on("get"+u,function(e){++s[e]}),t.on("delete"+u,function(e){delete s[e]}),t.on("clear"+u,function(){s={}}),a(t.memoized,{deleteRef:r(function(){var e=t.get(arguments);return null===e?null:s[e]?!--s[e]&&(t.delete(e),!0):null}),getRefCount:r(function(){var e=t.get(arguments);return null===e?0:s[e]?s[e]:0})})}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(){return[a.default]}Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var o=n(558),a=r(o)},function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);
+return t.default=e,t}function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){var e={components:{App:D.default,authorizationPopup:P.default,authorizeBtn:j.default,authorizeOperationBtn:F.default,auths:N.default,authError:L.default,oauth2:H.default,apiKeyAuth:q.default,basicAuth:K.default,clear:G.default,liveResponse:Y.default,info:Ce.default,onlineValidatorBadge:Z.default,operations:ee.default,operation:ne.default,highlightCode:ie.default,responses:ae.default,response:ue.default,responseBody:le.default,parameters:fe.default,parameterRow:de.default,execute:ye.default,headers:ge.default,errors:be.default,contentType:xe.default,overview:Se.default,footer:Te.default,ParamBody:De.default,curl:Pe.default,schemes:je.default,modelExample:Fe.default,model:Ne.default,models:Le.default,TryItOutButton:qe.default,BaseLayout:Ke.default}},t={components:He},n={components:Ge};return[S.default,y.default,f.default,l.default,a.default,u.default,d.default,e,t,b.default,n,x.default,g.default,C.default,T.default]};var o=n(559),a=i(o),s=n(574),u=i(s),c=n(578),l=i(c),p=n(618),f=i(p),h=n(842),d=i(h),m=n(843),y=i(m),v=n(844),g=i(v),_=n(876),b=i(_),w=n(1184),x=i(w),k=n(1189),S=i(k),E=n(1191),C=i(E),A=n(1240),T=i(A),O=n(1241),D=i(O),M=n(1242),P=i(M),I=n(1243),j=i(I),R=n(1244),F=i(R),B=n(1246),N=i(B),z=n(1247),L=i(z),U=n(1248),q=i(U),W=n(1249),K=i(W),V=n(1250),H=i(V),J=n(1252),G=i(J),X=n(1253),Y=i(X),$=n(1254),Z=i($),Q=n(1255),ee=i(Q),te=n(1256),ne=i(te),re=n(1260),ie=i(re),oe=n(1261),ae=i(oe),se=n(1262),ue=i(se),ce=n(1263),le=i(ce),pe=n(1265),fe=i(pe),he=n(1266),de=i(he),me=n(1267),ye=i(me),ve=n(1268),ge=i(ve),_e=n(1269),be=i(_e),we=n(1289),xe=i(we),ke=n(1290),Se=i(ke),Ee=n(1354),Ce=i(Ee),Ae=n(1355),Te=i(Ae),Oe=n(1356),De=i(Oe),Me=n(1357),Pe=i(Me),Ie=n(1359),je=i(Ie),Re=n(1360),Fe=i(Re),Be=n(1361),Ne=i(Be),ze=n(1362),Le=i(ze),Ue=n(1363),qe=i(Ue),We=n(1364),Ke=i(We),Ve=n(1291),He=r(Ve),Je=n(1365),Ge=r(Je)},function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return{statePlugins:{err:{reducers:(0,a.default)(e),actions:u,selectors:l}}}};var o=n(560),a=i(o),s=n(334),u=r(s),c=n(572),l=r(c)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t;return t={},i(t,o.NEW_THROWN_ERR,function(t,n){var r=n.payload,i=Object.assign(f,r,{type:"thrown"});return t.update("errors",function(e){return(e||(0,u.List)()).push((0,u.fromJS)(i))}).update("errors",function(t){return(0,p.default)(t,e.getSystem())})}),i(t,o.NEW_THROWN_ERR_BATCH,function(t,n){var r=n.payload;return r=r.map(function(e){return(0,u.fromJS)(Object.assign(f,e,{type:"thrown"}))}),t.update("errors",function(e){return(e||(0,u.List)()).concat((0,u.fromJS)(r))}).update("errors",function(t){return(0,p.default)(t,e.getSystem())})}),i(t,o.NEW_SPEC_ERR,function(t,n){var r=n.payload,i=(0,u.fromJS)(r);return i=i.set("type","spec"),t.update("errors",function(e){return(e||(0,u.List)()).push((0,u.fromJS)(i)).sortBy(function(e){return e.get("line")})}).update("errors",function(t){return(0,p.default)(t,e.getSystem())})}),i(t,o.NEW_AUTH_ERR,function(t,n){var r=n.payload,i=(0,u.fromJS)(Object.assign({},r));return i=i.set("type","auth"),t.update("errors",function(e){return(e||(0,u.List)()).push((0,u.fromJS)(i))}).update("errors",function(t){return(0,p.default)(t,e.getSystem())})}),i(t,o.CLEAR,function(e,t){var n=t.payload;if(n){var r=c.default.fromJS((0,s.default)((e.get("errors")||(0,u.List)()).toJS(),n));return e.merge({errors:r})}}),t};var o=n(334),a=n(561),s=r(a),u=n(326),c=r(u),l=n(565),p=r(l),f={line:0,level:"error",message:"Unknown error"}},function(e,t,n){function r(e,t){var n=s(e)?i:o;return n(e,u(a(t,3)))}var i=n(562),o=n(563),a=n(401),s=n(347),u=n(564);e.exports=r},function(e,t){function n(e,t){for(var n=-1,r=null==e?0:e.length,i=0,o=[];++n-1||c.push({name:o(e).replace(".js","").replace("./",""),transform:u(e).transform}))})},function(e,t,n){function r(e,t,n){var r=u(e)?i:s,c=arguments.length<3;return r(e,a(t,4),n,c,o)}var i=n(358),o=n(463),a=n(401),s=n(567),u=n(347);e.exports=r},function(e,t){function n(e,t,n,r,i){return i(e,function(e,i,o){n=r?(r=!1,e):t(n,e,i,o)}),n}e.exports=n},function(e,t,n){function r(e){return n(i(e))}function i(e){return o[e]||function(){throw new Error("Cannot find module '"+e+"'.")}()}var o={"./not-of-type.js":569,"./parameter-oneof.js":570,"./strip-instance.js":571};r.keys=function(){return Object.keys(o)},r.resolve=i,e.exports=r,r.id=568},function(e,t){"use strict";function n(e){return e.map(function(e){var t="is not of a type(s)",n=e.get("message").indexOf(t);if(n>-1){var i=e.get("message").slice(n+t.length).split(",");return e.set("message",e.get("message").slice(0,n)+r(i))}return e})}function r(e){return e.reduce(function(e,t,n,r){return n===r.length-1&&r.length>1?e+"or "+t:r[n+1]&&r.length>2?e+t+", ":r[n+1]?e+t+" ":e+t},"should be a")}Object.defineProperty(t,"__esModule",{value:!0}),t.transform=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){t.jsSpec;return e}Object.defineProperty(t,"__esModule",{value:!0}),t.transform=i;var o=n(448);r(o),n(326)},function(e,t){"use strict";function n(e){return e.map(function(e){return e.set("message",r(e.get("message"),"instance."))})}function r(e,t){return e.replace(new RegExp(t,"g"),"")}Object.defineProperty(t,"__esModule",{value:!0}),t.transform=n},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.lastError=t.allErrors=void 0;var r=n(326),i=n(573),o=function(e){return e},a=t.allErrors=(0,i.createSelector)(o,function(e){return e.get("errors",(0,r.List)())});t.lastError=(0,i.createSelector)(a,function(e){return e.last()})},function(e,t){"use strict";function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t1?t-1:0),i=1;i2?r-2:0),o=2;o1&&void 0!==arguments[1])||arguments[1];return e=(0,a.normalizeArray)(e),{type:c,payload:{thing:e,shown:t}}}function o(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return e=(0,a.normalizeArray)(e),{type:u,payload:{thing:e,mode:t}}}Object.defineProperty(t,"__esModule",{value:!0}),t.SHOW=t.UPDATE_MODE=t.UPDATE_LAYOUT=void 0,t.updateLayout=r,t.show=i,t.changeMode=o;var a=n(336),s=t.UPDATE_LAYOUT="layout_update_layout",u=t.UPDATE_MODE="layout_update_mode",c=t.SHOW="layout_show"},function(e,t,n){"use strict";function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t2&&void 0!==arguments[2]?arguments[2]:"";return t=(0,o.normalizeArray)(t),e.getIn(["modes"].concat(r(t)),n)},t.showSummary=(0,i.createSelector)(a,function(e){return!s(e,"editor")})},function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{statePlugins:{spec:{wrapActions:f,reducers:a.default,actions:u,selectors:l}}}};var o=n(579),a=i(o),s=n(580),u=r(s),c=n(616),l=r(c),p=n(617),f=r(p)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function o(e){return e instanceof Error?{type:E,error:!0,payload:e}:"string"==typeof e?{type:E,payload:e.replace(/\t/g," ")||""}:{type:E,payload:""}}function a(e){return{type:B,payload:e}}function s(e){return{type:C,payload:e}}function u(e){if(!e||"object"!==("undefined"==typeof e?"undefined":g(e)))throw new Error("updateJson must only accept a simple JSON object");return{type:A,payload:e}}function c(e,t,n,r){return{type:T,payload:{path:e,value:n,paramName:t,isXml:r}}}function l(e){return{type:O,payload:{pathMethod:e}}}function p(e){return{type:R,payload:{pathMethod:e}}}function f(e,t){return{type:F,payload:{path:e,value:t,key:"consumes_value"}}}function h(e,t){return{type:F,payload:{path:e,value:t,key:"produces_value"}}}function d(e,t){return{type:I,payload:{path:e,method:t}}}function m(e,t){return{type:j,payload:{path:e,method:t}}}function y(e,t,n){return{type:N,payload:{scheme:e,path:t,method:n}}}Object.defineProperty(t,"__esModule",{value:!0}),t.execute=t.executeRequest=t.logRequest=t.setRequest=t.setResponse=t.formatIntoYaml=t.resolveSpec=t.parseToJson=t.SET_SCHEME=t.UPDATE_RESOLVED=t.UPDATE_OPERATION_VALUE=t.ClEAR_VALIDATE_PARAMS=t.CLEAR_REQUEST=t.CLEAR_RESPONSE=t.LOG_REQUEST=t.SET_REQUEST=t.SET_RESPONSE=t.VALIDATE_PARAMS=t.UPDATE_PARAM=t.UPDATE_JSON=t.UPDATE_URL=t.UPDATE_SPEC=void 0;var v=Object.assign||function(e){for(var t=1;t0){var i=n.map(function(e){return console.error(e),e.line=e.fullPath?l(p,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",Object.defineProperty(e,"message",{enumerable:!0,value:e.message}),e});o.newThrownErrBatch(i)}return r.updateResolved(t)})}},t.formatIntoYaml=function(){return function(e){var t=e.specActions,n=e.specSelectors,r=n.specStr,i=t.updateSpec;try{var o=b.default.safeDump(b.default.safeLoad(r()),{indent:2});i(o)}catch(e){i(e)}}},t.setResponse=function(e,t,n){return{payload:{path:e,method:t,res:n},type:D}},t.setRequest=function(e,t,n){return{payload:{path:e,method:t,req:n},type:M}},t.logRequest=function(e){return{payload:e,type:P}},t.executeRequest=function(e){return function(t){var n=t.fn,r=t.specActions,i=t.specSelectors,o=e.pathName,a=e.method;e.contextUrl=(0,x.default)(i.url()).toString();var s=Object.assign({},e);return o&&a&&(s.operationId=a.toLowerCase()+"-"+o),s=n.buildRequest(s),r.setRequest(e.pathName,e.method,s),n.execute(e).then(function(t){return r.setResponse(e.pathName,e.method,t)}).catch(function(t){return r.setResponse(e.pathName,e.method,{error:!0,err:(0,S.default)(t)})})}},function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.path,n=e.method,r=i(e,["path","method"]);return function(e){var i=e.fn.fetch,o=e.specSelectors,a=e.specActions,s=o.spec().toJS(),u=o.operationScheme(t,n),c=o.contentTypeValues([t,n]).toJS(),l=c.requestContentType,p=c.responseContentType,f=/xml/i.test(l),h=o.parameterValues([t,n],f).toJS();return a.executeRequest(v({fetch:i,spec:s,pathName:t,method:n,parameters:h,requestContentType:l,scheme:u,responseContentType:p},r))}});t.execute=z},[1474,582],[1475,583,611,589,588,592,591,590,587,606,585,592,587,606],[1476,584,585,586,587,606],function(e,t){"use strict";function n(e){return"undefined"==typeof e||null===e}function r(e){return"object"==typeof e&&null!==e}function i(e){return Array.isArray(e)?e:n(e)?[]:[e]}function o(e,t){var n,r,i,o;if(t)for(o=Object.keys(t),n=0,r=o.length;n=0;--i){var o=this.leading[i];t.end.offset>=o.start&&(n.unshift(o.comment),this.leading.splice(i,1),this.trailing.splice(i,1))}n.length&&(e.innerComments=n)}},e.prototype.findTrailingComments=function(e,t){var n=[];if(this.trailing.length>0){for(var r=this.trailing.length-1;r>=0;--r){var i=this.trailing[r];i.start>=t.end.offset&&n.unshift(i.comment)}return this.trailing.length=0,n}var o=this.stack[this.stack.length-1];if(o&&o.node.trailingComments){var a=o.node.trailingComments[0];a&&a.range[0]>=t.end.offset&&(n=o.node.trailingComments,delete o.node.trailingComments)}return n},e.prototype.findLeadingComments=function(e,t){for(var n,r=[];this.stack.length>0;){var i=this.stack[this.stack.length-1];if(!(i&&i.start>=t.start.offset))break;n=this.stack.pop().node}if(n){for(var o=n.leadingComments?n.leadingComments.length:0,a=o-1;a>=0;--a){var s=n.leadingComments[a];s.range[1]<=t.start.offset&&(r.unshift(s),n.leadingComments.splice(a,1))}return n.leadingComments&&0===n.leadingComments.length&&delete n.leadingComments,r}for(var a=this.leading.length-1;a>=0;--a){var i=this.leading[a];i.start<=t.start.offset&&(r.unshift(i.comment),this.leading.splice(a,1))}return r},e.prototype.visitNode=function(e,t){if(!(e.type===r.Syntax.Program&&e.body.length>0)){this.insertInnerComments(e,t);var n=this.findTrailingComments(e,t),i=this.findLeadingComments(e,t);i.length>0&&(e.leadingComments=i),n.length>0&&(e.trailingComments=n),this.stack.push({node:e,start:t.start.offset})}},e.prototype.visitComment=function(e,t){var n="L"===e.type[0]?"Line":"Block",r={type:n,value:e.value};if(e.range&&(r.range=e.range),e.loc&&(r.loc=e.loc),this.comments.push(r),this.attach){var i={comment:{type:n,value:e.value,range:[t.start.offset,t.end.offset]},start:t.start.offset};e.loc&&(i.comment.loc=e.loc),e.type=n,this.leading.push(i),this.trailing.push(i)}},e.prototype.visit=function(e,t){"LineComment"===e.type?this.visitComment(e,t):"BlockComment"===e.type?this.visitComment(e,t):this.attach&&this.visitNode(e,t)},e}();t.CommentHandler=i},function(e,t){"use strict";t.Syntax={AssignmentExpression:"AssignmentExpression",AssignmentPattern:"AssignmentPattern",ArrayExpression:"ArrayExpression",ArrayPattern:"ArrayPattern",ArrowFunctionExpression:"ArrowFunctionExpression",BlockStatement:"BlockStatement",BinaryExpression:"BinaryExpression",BreakStatement:"BreakStatement",CallExpression:"CallExpression",CatchClause:"CatchClause",ClassBody:"ClassBody",ClassDeclaration:"ClassDeclaration",ClassExpression:"ClassExpression",ConditionalExpression:"ConditionalExpression",ContinueStatement:"ContinueStatement",DoWhileStatement:"DoWhileStatement",DebuggerStatement:"DebuggerStatement",EmptyStatement:"EmptyStatement",ExportAllDeclaration:"ExportAllDeclaration",ExportDefaultDeclaration:"ExportDefaultDeclaration",ExportNamedDeclaration:"ExportNamedDeclaration",ExportSpecifier:"ExportSpecifier",ExpressionStatement:"ExpressionStatement",ForStatement:"ForStatement",ForOfStatement:"ForOfStatement",ForInStatement:"ForInStatement",FunctionDeclaration:"FunctionDeclaration",FunctionExpression:"FunctionExpression",Identifier:"Identifier",IfStatement:"IfStatement",ImportDeclaration:"ImportDeclaration",ImportDefaultSpecifier:"ImportDefaultSpecifier",ImportNamespaceSpecifier:"ImportNamespaceSpecifier",ImportSpecifier:"ImportSpecifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",MetaProperty:"MetaProperty",MethodDefinition:"MethodDefinition",NewExpression:"NewExpression",ObjectExpression:"ObjectExpression",ObjectPattern:"ObjectPattern",Program:"Program",Property:"Property",RestElement:"RestElement",ReturnStatement:"ReturnStatement",SequenceExpression:"SequenceExpression",SpreadElement:"SpreadElement",Super:"Super",SwitchCase:"SwitchCase",SwitchStatement:"SwitchStatement",TaggedTemplateExpression:"TaggedTemplateExpression",TemplateElement:"TemplateElement",TemplateLiteral:"TemplateLiteral",ThisExpression:"ThisExpression",ThrowStatement:"ThrowStatement",TryStatement:"TryStatement",UnaryExpression:"UnaryExpression",UpdateExpression:"UpdateExpression",VariableDeclaration:"VariableDeclaration",VariableDeclarator:"VariableDeclarator",WhileStatement:"WhileStatement",WithStatement:"WithStatement",YieldExpression:"YieldExpression"}},function(e,t,n){"use strict";var r=n(4),i=n(5),o=n(6),a=n(7),s=n(8),u=n(2),c=n(10),l="ArrowParameterPlaceHolder",p=function(){function e(e,t,n){void 0===t&&(t={}),this.config={range:"boolean"==typeof t.range&&t.range,loc:"boolean"==typeof t.loc&&t.loc,source:null,tokens:"boolean"==typeof t.tokens&&t.tokens,comment:"boolean"==typeof t.comment&&t.comment,tolerant:"boolean"==typeof t.tolerant&&t.tolerant},this.config.loc&&t.source&&null!==t.source&&(this.config.source=String(t.source)),this.delegate=n,this.errorHandler=new o.ErrorHandler,this.errorHandler.tolerant=this.config.tolerant,this.scanner=new s.Scanner(e,this.errorHandler),this.scanner.trackComment=this.config.comment,this.operatorPrecedence={")":0,";":0,",":0,"=":0,"]":0,"||":1,"&&":2,"|":3,"^":4,"&":5,"==":6,"!=":6,"===":6,"!==":6,"<":7,">":7,"<=":7,">=":7,"<<":8,">>":8,">>>":8,"+":9,"-":9,"*":11,"/":11,"%":11},this.sourceType=t&&"module"===t.sourceType?"module":"script",this.lookahead=null,this.hasLineTerminator=!1,this.context={allowIn:!0,allowYield:!0,firstCoverInitializedNameError:null,isAssignmentTarget:!1,isBindingElement:!1,inFunctionBody:!1,inIteration:!1,inSwitch:!1,labelSet:{},strict:"module"===this.sourceType},this.tokens=[],this.startMarker={index:0,lineNumber:this.scanner.lineNumber,lineStart:0},this.lastMarker={index:0,lineNumber:this.scanner.lineNumber,lineStart:0},this.nextToken(),this.lastMarker={index:this.scanner.index,lineNumber:this.scanner.lineNumber,lineStart:this.scanner.lineStart}}return e.prototype.throwError=function(e){for(var t=[],n=1;n0&&this.delegate)for(var t=0;t>="===e||">>>="===e||"&="===e||"^="===e||"|="===e},e.prototype.isolateCoverGrammar=function(e){var t=this.context.isBindingElement,n=this.context.isAssignmentTarget,r=this.context.firstCoverInitializedNameError;this.context.isBindingElement=!0,this.context.isAssignmentTarget=!0,this.context.firstCoverInitializedNameError=null;var i=e.call(this);return null!==this.context.firstCoverInitializedNameError&&this.throwUnexpectedToken(this.context.firstCoverInitializedNameError),this.context.isBindingElement=t,this.context.isAssignmentTarget=n,this.context.firstCoverInitializedNameError=r,i},e.prototype.inheritCoverGrammar=function(e){var t=this.context.isBindingElement,n=this.context.isAssignmentTarget,r=this.context.firstCoverInitializedNameError;this.context.isBindingElement=!0,this.context.isAssignmentTarget=!0,this.context.firstCoverInitializedNameError=null;var i=e.call(this);return this.context.isBindingElement=this.context.isBindingElement&&t,this.context.isAssignmentTarget=this.context.isAssignmentTarget&&n,this.context.firstCoverInitializedNameError=r||this.context.firstCoverInitializedNameError,i},e.prototype.consumeSemicolon=function(){this.match(";")?this.nextToken():this.hasLineTerminator||(this.lookahead.type===a.Token.EOF||this.match("}")||this.throwUnexpectedToken(this.lookahead),this.lastMarker.index=this.startMarker.index,this.lastMarker.lineNumber=this.startMarker.lineNumber,this.lastMarker.lineStart=this.startMarker.lineStart)},e.prototype.parsePrimaryExpression=function(){var e,t,n,r,o=this.createNode();switch(this.lookahead.type){case a.Token.Identifier:"module"===this.sourceType&&"await"===this.lookahead.value&&this.tolerateUnexpectedToken(this.lookahead),e=this.finalize(o,new c.Identifier(this.nextToken().value));break;case a.Token.NumericLiteral:case a.Token.StringLiteral:this.context.strict&&this.lookahead.octal&&this.tolerateUnexpectedToken(this.lookahead,i.Messages.StrictOctalLiteral),this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1,n=this.nextToken(),r=this.getTokenRaw(n),e=this.finalize(o,new c.Literal(n.value,r));break;case a.Token.BooleanLiteral:this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1,n=this.nextToken(),n.value="true"===n.value,r=this.getTokenRaw(n),e=this.finalize(o,new c.Literal(n.value,r));break;case a.Token.NullLiteral:this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1,n=this.nextToken(),n.value=null,r=this.getTokenRaw(n),e=this.finalize(o,new c.Literal(n.value,r));break;case a.Token.Template:e=this.parseTemplateLiteral();break;case a.Token.Punctuator:switch(t=this.lookahead.value){case"(":this.context.isBindingElement=!1,e=this.inheritCoverGrammar(this.parseGroupExpression);break;case"[":e=this.inheritCoverGrammar(this.parseArrayInitializer);break;case"{":e=this.inheritCoverGrammar(this.parseObjectInitializer);break;case"/":case"/=":this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1,this.scanner.index=this.startMarker.index,n=this.nextRegexToken(),r=this.getTokenRaw(n),e=this.finalize(o,new c.RegexLiteral(n.value,r,n.regex));break;default:this.throwUnexpectedToken(this.nextToken())}break;case a.Token.Keyword:!this.context.strict&&this.context.allowYield&&this.matchKeyword("yield")?e=this.parseIdentifierName():!this.context.strict&&this.matchKeyword("let")?e=this.finalize(o,new c.Identifier(this.nextToken().value)):(this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1,this.matchKeyword("function")?e=this.parseFunctionExpression():this.matchKeyword("this")?(this.nextToken(),e=this.finalize(o,new c.ThisExpression)):this.matchKeyword("class")?e=this.parseClassExpression():this.throwUnexpectedToken(this.nextToken()));break;default:this.throwUnexpectedToken(this.nextToken())}return e},e.prototype.parseSpreadElement=function(){var e=this.createNode();this.expect("...");var t=this.inheritCoverGrammar(this.parseAssignmentExpression);return this.finalize(e,new c.SpreadElement(t))},e.prototype.parseArrayInitializer=function(){var e=this.createNode(),t=[];for(this.expect("[");!this.match("]");)if(this.match(","))this.nextToken(),t.push(null);else if(this.match("...")){var n=this.parseSpreadElement();this.match("]")||(this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1,this.expect(",")),t.push(n)}else t.push(this.inheritCoverGrammar(this.parseAssignmentExpression)),this.match("]")||this.expect(",");return this.expect("]"),this.finalize(e,new c.ArrayExpression(t))},e.prototype.parsePropertyMethod=function(e){this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1;var t=this.context.strict,n=this.isolateCoverGrammar(this.parseFunctionSourceElements);return this.context.strict&&e.firstRestricted&&this.tolerateUnexpectedToken(e.firstRestricted,e.message),this.context.strict&&e.stricted&&this.tolerateUnexpectedToken(e.stricted,e.message),this.context.strict=t,n},e.prototype.parsePropertyMethodFunction=function(){var e=!1,t=this.createNode(),n=this.context.allowYield;this.context.allowYield=!1;var r=this.parseFormalParameters(),i=this.parsePropertyMethod(r);return this.context.allowYield=n,this.finalize(t,new c.FunctionExpression(null,r.params,i,e))},e.prototype.parseObjectPropertyKey=function(){var e=this.createNode(),t=this.nextToken(),n=null;switch(t.type){case a.Token.StringLiteral:case a.Token.NumericLiteral:this.context.strict&&t.octal&&this.tolerateUnexpectedToken(t,i.Messages.StrictOctalLiteral);var r=this.getTokenRaw(t);n=this.finalize(e,new c.Literal(t.value,r));break;case a.Token.Identifier:case a.Token.BooleanLiteral:case a.Token.NullLiteral:case a.Token.Keyword:n=this.finalize(e,new c.Identifier(t.value));break;case a.Token.Punctuator:"["===t.value?(n=this.isolateCoverGrammar(this.parseAssignmentExpression),this.expect("]")):this.throwUnexpectedToken(t);break;default:this.throwUnexpectedToken(t)}return n},e.prototype.isPropertyKey=function(e,t){return e.type===u.Syntax.Identifier&&e.name===t||e.type===u.Syntax.Literal&&e.value===t},e.prototype.parseObjectProperty=function(e){var t,n,r,o=this.createNode(),s=this.lookahead,u=!1,l=!1,p=!1;s.type===a.Token.Identifier?(this.nextToken(),n=this.finalize(o,new c.Identifier(s.value))):this.match("*")?this.nextToken():(u=this.match("["),n=this.parseObjectPropertyKey());var f=this.qualifiedPropertyName(this.lookahead);if(s.type===a.Token.Identifier&&"get"===s.value&&f)t="get",u=this.match("["),n=this.parseObjectPropertyKey(),this.context.allowYield=!1,r=this.parseGetterMethod();else if(s.type===a.Token.Identifier&&"set"===s.value&&f)t="set",u=this.match("["),n=this.parseObjectPropertyKey(),r=this.parseSetterMethod();else if(s.type===a.Token.Punctuator&&"*"===s.value&&f)t="init",u=this.match("["),n=this.parseObjectPropertyKey(),r=this.parseGeneratorMethod(),l=!0;else if(n||this.throwUnexpectedToken(this.lookahead),t="init",this.match(":"))!u&&this.isPropertyKey(n,"__proto__")&&(e.value&&this.tolerateError(i.Messages.DuplicateProtoProperty),e.value=!0),this.nextToken(),r=this.inheritCoverGrammar(this.parseAssignmentExpression);else if(this.match("("))r=this.parsePropertyMethodFunction(),l=!0;else if(s.type===a.Token.Identifier){var h=this.finalize(o,new c.Identifier(s.value));if(this.match("=")){this.context.firstCoverInitializedNameError=this.lookahead,this.nextToken(),p=!0;var d=this.isolateCoverGrammar(this.parseAssignmentExpression);r=this.finalize(o,new c.AssignmentPattern(h,d))}else p=!0,r=h}else this.throwUnexpectedToken(this.nextToken());return this.finalize(o,new c.Property(t,n,u,r,l,p))},e.prototype.parseObjectInitializer=function(){var e=this.createNode();this.expect("{");for(var t=[],n={value:!1};!this.match("}");)t.push(this.parseObjectProperty(n)),this.match("}")||this.expectCommaSeparator();return this.expect("}"),this.finalize(e,new c.ObjectExpression(t))},e.prototype.parseTemplateHead=function(){r.assert(this.lookahead.head,"Template literal must start with a template head");var e=this.createNode(),t=this.nextToken(),n={raw:t.value.raw,cooked:t.value.cooked};return this.finalize(e,new c.TemplateElement(n,t.tail))},e.prototype.parseTemplateElement=function(){this.lookahead.type!==a.Token.Template&&this.throwUnexpectedToken();var e=this.createNode(),t=this.nextToken(),n={raw:t.value.raw,cooked:t.value.cooked};return this.finalize(e,new c.TemplateElement(n,t.tail))},e.prototype.parseTemplateLiteral=function(){var e=this.createNode(),t=[],n=[],r=this.parseTemplateHead();for(n.push(r);!r.tail;)t.push(this.parseExpression()),r=this.parseTemplateElement(),n.push(r);return this.finalize(e,new c.TemplateLiteral(n,t))},e.prototype.reinterpretExpressionAsPattern=function(e){switch(e.type){case u.Syntax.Identifier:case u.Syntax.MemberExpression:case u.Syntax.RestElement:case u.Syntax.AssignmentPattern:break;case u.Syntax.SpreadElement:e.type=u.Syntax.RestElement,this.reinterpretExpressionAsPattern(e.argument);break;case u.Syntax.ArrayExpression:e.type=u.Syntax.ArrayPattern;for(var t=0;t")||this.expect("=>"),e={type:l,params:[]};else{var t=this.lookahead,n=[];if(this.match("..."))e=this.parseRestElement(n),this.expect(")"),this.match("=>")||this.expect("=>"),e={type:l,params:[e]};else{var r=!1;if(this.context.isBindingElement=!0,e=this.inheritCoverGrammar(this.parseAssignmentExpression),this.match(",")){var i=[];for(this.context.isAssignmentTarget=!1,i.push(e);this.startMarker.index")||this.expect("=>"),this.context.isBindingElement=!1;for(var o=0;o")&&(e.type===u.Syntax.Identifier&&"yield"===e.name&&(r=!0,e={type:l,params:[e]}),!r)){if(this.context.isBindingElement||this.throwUnexpectedToken(this.lookahead),e.type===u.Syntax.SequenceExpression)for(var o=0;o0){this.nextToken(),n.prec=r,this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1;for(var i=[e,this.lookahead],o=t,a=this.isolateCoverGrammar(this.parseExponentiationExpression),s=[o,n,a];;){if(r=this.binaryPrecedence(this.lookahead),r<=0)break;for(;s.length>2&&r<=s[s.length-2].prec;){a=s.pop();var u=s.pop().value;o=s.pop(),i.pop();var l=this.startNode(i[i.length-1]);s.push(this.finalize(l,new c.BinaryExpression(u,o,a)))}n=this.nextToken(),n.prec=r,s.push(n),i.push(this.lookahead),s.push(this.isolateCoverGrammar(this.parseExponentiationExpression))}var p=s.length-1;for(t=s[p],i.pop();p>1;){var l=this.startNode(i.pop());t=this.finalize(l,new c.BinaryExpression(s[p-1].value,s[p-2],t)),p-=2}}return t},e.prototype.parseConditionalExpression=function(){var e=this.lookahead,t=this.inheritCoverGrammar(this.parseBinaryExpression);if(this.match("?")){this.nextToken();var n=this.context.allowIn;this.context.allowIn=!0;var r=this.isolateCoverGrammar(this.parseAssignmentExpression);this.context.allowIn=n,this.expect(":");var i=this.isolateCoverGrammar(this.parseAssignmentExpression);t=this.finalize(this.startNode(e),new c.ConditionalExpression(t,r,i)),this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1}return t},e.prototype.checkPatternParam=function(e,t){switch(t.type){case u.Syntax.Identifier:this.validateParam(e,t,t.name);break;case u.Syntax.RestElement:this.checkPatternParam(e,t.argument);break;case u.Syntax.AssignmentPattern:this.checkPatternParam(e,t.left);break;case u.Syntax.ArrayPattern:for(var n=0;n")){this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1;var r=this.reinterpretAsCoverFormalsList(e);if(r){this.hasLineTerminator&&this.tolerateUnexpectedToken(this.lookahead),this.context.firstCoverInitializedNameError=null;var o=this.context.strict,a=this.context.allowYield;this.context.allowYield=!0;var s=this.startNode(t);this.expect("=>");var p=this.match("{")?this.parseFunctionSourceElements():this.isolateCoverGrammar(this.parseAssignmentExpression),f=p.type!==u.Syntax.BlockStatement;this.context.strict&&r.firstRestricted&&this.throwUnexpectedToken(r.firstRestricted,r.message),this.context.strict&&r.stricted&&this.tolerateUnexpectedToken(r.stricted,r.message),e=this.finalize(s,new c.ArrowFunctionExpression(r.params,p,f)),this.context.strict=o,this.context.allowYield=a}}else if(this.matchAssign()){if(this.context.isAssignmentTarget||this.tolerateError(i.Messages.InvalidLHSInAssignment),this.context.strict&&e.type===u.Syntax.Identifier){var h=e;this.scanner.isRestrictedWord(h.name)&&this.tolerateUnexpectedToken(n,i.Messages.StrictLHSAssignment),this.scanner.isStrictModeReservedWord(h.name)&&this.tolerateUnexpectedToken(n,i.Messages.StrictReservedWord)}this.match("=")?this.reinterpretExpressionAsPattern(e):(this.context.isAssignmentTarget=!1,this.context.isBindingElement=!1),n=this.nextToken();var d=this.isolateCoverGrammar(this.parseAssignmentExpression);e=this.finalize(this.startNode(t),new c.AssignmentExpression(n.value,e,d)),this.context.firstCoverInitializedNameError=null}}return e},e.prototype.parseExpression=function(){var e=this.lookahead,t=this.isolateCoverGrammar(this.parseAssignmentExpression);if(this.match(",")){var n=[];for(n.push(t);this.startMarker.index",t.TokenName[n.Identifier]="Identifier",t.TokenName[n.Keyword]="Keyword",t.TokenName[n.NullLiteral]="Null",t.TokenName[n.NumericLiteral]="Numeric",t.TokenName[n.Punctuator]="Punctuator",t.TokenName[n.StringLiteral]="String",t.TokenName[n.RegularExpression]="RegularExpression",t.TokenName[n.Template]="Template"},function(e,t,n){"use strict";function r(e){return"0123456789abcdef".indexOf(e.toLowerCase())}function i(e){return"01234567".indexOf(e)}var o=n(4),a=n(5),s=n(9),u=n(7),c=function(){function e(e,t){this.source=e,this.errorHandler=t,this.trackComment=!1,this.length=e.length,this.index=0,this.lineNumber=e.length>0?1:0,this.lineStart=0,this.curlyStack=[]}return e.prototype.eof=function(){return this.index>=this.length},e.prototype.throwUnexpectedToken=function(e){void 0===e&&(e=a.Messages.UnexpectedTokenIllegal),this.errorHandler.throwError(this.index,this.lineNumber,this.index-this.lineStart+1,e)},e.prototype.tolerateUnexpectedToken=function(){this.errorHandler.tolerateError(this.index,this.lineNumber,this.index-this.lineStart+1,a.Messages.UnexpectedTokenIllegal)},e.prototype.skipSingleLineComment=function(e){var t,n,r;for(this.trackComment&&(t=[],n=this.index-e,r={start:{line:this.lineNumber,column:this.index-this.lineStart-e},end:{}});!this.eof();){var i=this.source.charCodeAt(this.index);if(++this.index,s.Character.isLineTerminator(i)){if(this.trackComment){r.end={line:this.lineNumber,column:this.index-this.lineStart-1};var o={multiLine:!1,slice:[n+e,this.index-1],range:[n,this.index-1],loc:r};t.push(o)}return 13===i&&10===this.source.charCodeAt(this.index)&&++this.index,++this.lineNumber,this.lineStart=this.index,t}}if(this.trackComment){r.end={line:this.lineNumber,column:this.index-this.lineStart};var o={multiLine:!1,slice:[n+e,this.index],range:[n,this.index],loc:r};t.push(o)}return t},e.prototype.skipMultiLineComment=function(){var e,t,n;for(this.trackComment&&(e=[],t=this.index-2,n={start:{line:this.lineNumber,column:this.index-this.lineStart-2},end:{}});!this.eof();){var r=this.source.charCodeAt(this.index);if(s.Character.isLineTerminator(r))13===r&&10===this.source.charCodeAt(this.index+1)&&++this.index,++this.lineNumber,++this.index,this.lineStart=this.index;else if(42===r){if(47===this.source.charCodeAt(this.index+1)){if(this.index+=2,this.trackComment){n.end={line:this.lineNumber,column:this.index-this.lineStart};var i={multiLine:!0,slice:[t+2,this.index-2],range:[t,this.index],loc:n};e.push(i)}return e}++this.index}else++this.index}if(this.trackComment){n.end={line:this.lineNumber,column:this.index-this.lineStart};var i={multiLine:!0,slice:[t+2,this.index],range:[t,this.index],loc:n};e.push(i)}return this.tolerateUnexpectedToken(),e},e.prototype.scanComments=function(){var e;this.trackComment&&(e=[]);for(var t=0===this.index;!this.eof();){var n=this.source.charCodeAt(this.index);if(s.Character.isWhiteSpace(n))++this.index;else if(s.Character.isLineTerminator(n))++this.index,13===n&&10===this.source.charCodeAt(this.index)&&++this.index,++this.lineNumber,this.lineStart=this.index,t=!0;else if(47===n)if(n=this.source.charCodeAt(this.index+1),47===n){this.index+=2;var r=this.skipSingleLineComment(2);this.trackComment&&(e=e.concat(r)),t=!0}else{if(42!==n)break;this.index+=2;var r=this.skipMultiLineComment();this.trackComment&&(e=e.concat(r))}else if(t&&45===n){if(45!==this.source.charCodeAt(this.index+1)||62!==this.source.charCodeAt(this.index+2))break;this.index+=3;var r=this.skipSingleLineComment(3);this.trackComment&&(e=e.concat(r))}else{if(60!==n)break;if("!--"!==this.source.slice(this.index+1,this.index+4))break;this.index+=4;var r=this.skipSingleLineComment(4);this.trackComment&&(e=e.concat(r))}}return e},e.prototype.isFutureReservedWord=function(e){
+switch(e){case"enum":case"export":case"import":case"super":return!0;default:return!1}},e.prototype.isStrictModeReservedWord=function(e){switch(e){case"implements":case"interface":case"package":case"private":case"protected":case"public":case"static":case"yield":case"let":return!0;default:return!1}},e.prototype.isRestrictedWord=function(e){return"eval"===e||"arguments"===e},e.prototype.isKeyword=function(e){switch(e.length){case 2:return"if"===e||"in"===e||"do"===e;case 3:return"var"===e||"for"===e||"new"===e||"try"===e||"let"===e;case 4:return"this"===e||"else"===e||"case"===e||"void"===e||"with"===e||"enum"===e;case 5:return"while"===e||"break"===e||"catch"===e||"throw"===e||"const"===e||"yield"===e||"class"===e||"super"===e;case 6:return"return"===e||"typeof"===e||"delete"===e||"switch"===e||"export"===e||"import"===e;case 7:return"default"===e||"finally"===e||"extends"===e;case 8:return"function"===e||"continue"===e||"debugger"===e;case 10:return"instanceof"===e;default:return!1}},e.prototype.codePointAt=function(e){var t=this.source.charCodeAt(e);if(t>=55296&&t<=56319){var n=this.source.charCodeAt(e+1);if(n>=56320&&n<=57343){var r=t;t=1024*(r-55296)+n-56320+65536}}return t},e.prototype.scanHexEscape=function(e){for(var t="u"===e?4:2,n=0,i=0;i1114111||"}"!==e)&&this.throwUnexpectedToken(),s.Character.fromCodePoint(t)},e.prototype.getIdentifier=function(){for(var e=this.index++;!this.eof();){var t=this.source.charCodeAt(this.index);if(92===t)return this.index=e,this.getComplexIdentifier();if(t>=55296&&t<57343)return this.index=e,this.getComplexIdentifier();if(!s.Character.isIdentifierPart(t))break;++this.index}return this.source.slice(e,this.index)},e.prototype.getComplexIdentifier=function(){var e=this.codePointAt(this.index),t=s.Character.fromCodePoint(e);this.index+=t.length;var n;for(92===e&&(117!==this.source.charCodeAt(this.index)&&this.throwUnexpectedToken(),++this.index,"{"===this.source[this.index]?(++this.index,n=this.scanUnicodeCodePointEscape()):(n=this.scanHexEscape("u"),e=n.charCodeAt(0),n&&"\\"!==n&&s.Character.isIdentifierStart(e)||this.throwUnexpectedToken()),t=n);!this.eof()&&(e=this.codePointAt(this.index),s.Character.isIdentifierPart(e));)n=s.Character.fromCodePoint(e),t+=n,this.index+=n.length,92===e&&(t=t.substr(0,t.length-1),117!==this.source.charCodeAt(this.index)&&this.throwUnexpectedToken(),++this.index,"{"===this.source[this.index]?(++this.index,n=this.scanUnicodeCodePointEscape()):(n=this.scanHexEscape("u"),e=n.charCodeAt(0),n&&"\\"!==n&&s.Character.isIdentifierPart(e)||this.throwUnexpectedToken()),t+=n);return t},e.prototype.octalToDecimal=function(e){var t="0"!==e,n=i(e);return!this.eof()&&s.Character.isOctalDigit(this.source.charCodeAt(this.index))&&(t=!0,n=8*n+i(this.source[this.index++]),"0123".indexOf(e)>=0&&!this.eof()&&s.Character.isOctalDigit(this.source.charCodeAt(this.index))&&(n=8*n+i(this.source[this.index++]))),{code:n,octal:t}},e.prototype.scanIdentifier=function(){var e,t=this.index,n=92===this.source.charCodeAt(t)?this.getComplexIdentifier():this.getIdentifier();return e=1===n.length?u.Token.Identifier:this.isKeyword(n)?u.Token.Keyword:"null"===n?u.Token.NullLiteral:"true"===n||"false"===n?u.Token.BooleanLiteral:u.Token.Identifier,{type:e,value:n,lineNumber:this.lineNumber,lineStart:this.lineStart,start:t,end:this.index}},e.prototype.scanPunctuator=function(){var e={type:u.Token.Punctuator,value:"",lineNumber:this.lineNumber,lineStart:this.lineStart,start:this.index,end:this.index},t=this.source[this.index];switch(t){case"(":case"{":"{"===t&&this.curlyStack.push("{"),++this.index;break;case".":++this.index,"."===this.source[this.index]&&"."===this.source[this.index+1]&&(this.index+=2,t="...");break;case"}":++this.index,this.curlyStack.pop();break;case")":case";":case",":case"[":case"]":case":":case"?":case"~":++this.index;break;default:t=this.source.substr(this.index,4),">>>="===t?this.index+=4:(t=t.substr(0,3),"==="===t||"!=="===t||">>>"===t||"<<="===t||">>="===t||"**="===t?this.index+=3:(t=t.substr(0,2),"&&"===t||"||"===t||"=="===t||"!="===t||"+="===t||"-="===t||"*="===t||"/="===t||"++"===t||"--"===t||"<<"===t||">>"===t||"&="===t||"|="===t||"^="===t||"%="===t||"<="===t||">="===t||"=>"===t||"**"===t?this.index+=2:(t=this.source[this.index],"<>=!+-*%&|^/".indexOf(t)>=0&&++this.index)))}return this.index===e.start&&this.throwUnexpectedToken(),e.end=this.index,e.value=t,e},e.prototype.scanHexLiteral=function(e){for(var t="";!this.eof()&&s.Character.isHexDigit(this.source.charCodeAt(this.index));)t+=this.source[this.index++];return 0===t.length&&this.throwUnexpectedToken(),s.Character.isIdentifierStart(this.source.charCodeAt(this.index))&&this.throwUnexpectedToken(),{type:u.Token.NumericLiteral,value:parseInt("0x"+t,16),lineNumber:this.lineNumber,lineStart:this.lineStart,start:e,end:this.index}},e.prototype.scanBinaryLiteral=function(e){for(var t,n="";!this.eof()&&(t=this.source[this.index],"0"===t||"1"===t);)n+=this.source[this.index++];return 0===n.length&&this.throwUnexpectedToken(),this.eof()||(t=this.source.charCodeAt(this.index),(s.Character.isIdentifierStart(t)||s.Character.isDecimalDigit(t))&&this.throwUnexpectedToken()),{type:u.Token.NumericLiteral,value:parseInt(n,2),lineNumber:this.lineNumber,lineStart:this.lineStart,start:e,end:this.index}},e.prototype.scanOctalLiteral=function(e,t){var n="",r=!1;for(s.Character.isOctalDigit(e.charCodeAt(0))?(r=!0,n="0"+this.source[this.index++]):++this.index;!this.eof()&&s.Character.isOctalDigit(this.source.charCodeAt(this.index));)n+=this.source[this.index++];return r||0!==n.length||this.throwUnexpectedToken(),(s.Character.isIdentifierStart(this.source.charCodeAt(this.index))||s.Character.isDecimalDigit(this.source.charCodeAt(this.index)))&&this.throwUnexpectedToken(),{type:u.Token.NumericLiteral,value:parseInt(n,8),octal:r,lineNumber:this.lineNumber,lineStart:this.lineStart,start:t,end:this.index}},e.prototype.isImplicitOctalLiteral=function(){for(var e=this.index+1;e=0&&(r=r.replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g,function(e,t,r){var o=parseInt(t||r,16);return o>1114111&&i.throwUnexpectedToken(a.Messages.InvalidRegExp),o<=65535?String.fromCharCode(o):n}).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,n));try{RegExp(r)}catch(e){this.throwUnexpectedToken(a.Messages.InvalidRegExp)}try{return new RegExp(e,t)}catch(e){return null}},e.prototype.scanRegExpBody=function(){var e=this.source[this.index];o.assert("/"===e,"Regular expression literal must start with a slash");for(var t=this.source[this.index++],n=!1,r=!1;!this.eof();)if(e=this.source[this.index++],t+=e,"\\"===e)e=this.source[this.index++],s.Character.isLineTerminator(e.charCodeAt(0))&&this.throwUnexpectedToken(a.Messages.UnterminatedRegExp),t+=e;else if(s.Character.isLineTerminator(e.charCodeAt(0)))this.throwUnexpectedToken(a.Messages.UnterminatedRegExp);else if(n)"]"===e&&(n=!1);else{if("/"===e){r=!0;break}"["===e&&(n=!0)}r||this.throwUnexpectedToken(a.Messages.UnterminatedRegExp);var i=t.substr(1,t.length-2);return{value:i,literal:t}},e.prototype.scanRegExpFlags=function(){for(var e="",t="";!this.eof();){var n=this.source[this.index];if(!s.Character.isIdentifierPart(n.charCodeAt(0)))break;if(++this.index,"\\"!==n||this.eof())t+=n,e+=n;else if(n=this.source[this.index],"u"===n){++this.index;var r=this.index;if(n=this.scanHexEscape("u"))for(t+=n,e+="\\u";r=55296&&e<57343&&s.Character.isIdentifierStart(this.codePointAt(this.index))?this.scanIdentifier():this.scanPunctuator()},e}();t.Scanner=c},function(e,t){"use strict";var n={NonAsciiIdentifierStart:/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/,NonAsciiIdentifierPart:/[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/};t.Character={fromCodePoint:function(e){return e<65536?String.fromCharCode(e):String.fromCharCode(55296+(e-65536>>10))+String.fromCharCode(56320+(e-65536&1023))},isWhiteSpace:function(e){return 32===e||9===e||11===e||12===e||160===e||e>=5760&&[5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].indexOf(e)>=0},isLineTerminator:function(e){return 10===e||13===e||8232===e||8233===e},isIdentifierStart:function(e){return 36===e||95===e||e>=65&&e<=90||e>=97&&e<=122||92===e||e>=128&&n.NonAsciiIdentifierStart.test(t.Character.fromCodePoint(e))},isIdentifierPart:function(e){return 36===e||95===e||e>=65&&e<=90||e>=97&&e<=122||e>=48&&e<=57||92===e||e>=128&&n.NonAsciiIdentifierPart.test(t.Character.fromCodePoint(e))},isDecimalDigit:function(e){return e>=48&&e<=57},isHexDigit:function(e){return e>=48&&e<=57||e>=65&&e<=70||e>=97&&e<=102},isOctalDigit:function(e){return e>=48&&e<=55}}},function(e,t,n){"use strict";var r=n(2),i=function(){function e(e){this.type=r.Syntax.ArrayExpression,this.elements=e}return e}();t.ArrayExpression=i;var o=function(){function e(e){this.type=r.Syntax.ArrayPattern,this.elements=e}return e}();t.ArrayPattern=o;var a=function(){function e(e,t,n){this.type=r.Syntax.ArrowFunctionExpression,this.id=null,this.params=e,this.body=t,this.generator=!1,this.expression=n}return e}();t.ArrowFunctionExpression=a;var s=function(){function e(e,t,n){this.type=r.Syntax.AssignmentExpression,this.operator=e,this.left=t,this.right=n}return e}();t.AssignmentExpression=s;var u=function(){function e(e,t){this.type=r.Syntax.AssignmentPattern,this.left=e,this.right=t}return e}();t.AssignmentPattern=u;var c=function(){function e(e,t,n){var i="||"===e||"&&"===e;this.type=i?r.Syntax.LogicalExpression:r.Syntax.BinaryExpression,this.operator=e,this.left=t,this.right=n}return e}();t.BinaryExpression=c;var l=function(){function e(e){this.type=r.Syntax.BlockStatement,this.body=e}return e}();t.BlockStatement=l;var p=function(){function e(e){this.type=r.Syntax.BreakStatement,this.label=e}return e}();t.BreakStatement=p;var f=function(){function e(e,t){this.type=r.Syntax.CallExpression,this.callee=e,this.arguments=t}return e}();t.CallExpression=f;var h=function(){function e(e,t){this.type=r.Syntax.CatchClause,this.param=e,this.body=t}return e}();t.CatchClause=h;var d=function(){function e(e){this.type=r.Syntax.ClassBody,this.body=e}return e}();t.ClassBody=d;var m=function(){function e(e,t,n){this.type=r.Syntax.ClassDeclaration,this.id=e,this.superClass=t,this.body=n}return e}();t.ClassDeclaration=m;var y=function(){function e(e,t,n){this.type=r.Syntax.ClassExpression,this.id=e,this.superClass=t,this.body=n}return e}();t.ClassExpression=y;var v=function(){function e(e,t){this.type=r.Syntax.MemberExpression,this.computed=!0,this.object=e,this.property=t}return e}();t.ComputedMemberExpression=v;var g=function(){function e(e,t,n){this.type=r.Syntax.ConditionalExpression,this.test=e,this.consequent=t,this.alternate=n}return e}();t.ConditionalExpression=g;var _=function(){function e(e){this.type=r.Syntax.ContinueStatement,this.label=e}return e}();t.ContinueStatement=_;var b=function(){function e(){this.type=r.Syntax.DebuggerStatement}return e}();t.DebuggerStatement=b;var w=function(){function e(e,t){this.type=r.Syntax.ExpressionStatement,this.expression=e,this.directive=t}return e}();t.Directive=w;var x=function(){function e(e,t){this.type=r.Syntax.DoWhileStatement,this.body=e,this.test=t}return e}();t.DoWhileStatement=x;var k=function(){function e(){this.type=r.Syntax.EmptyStatement}return e}();t.EmptyStatement=k;var S=function(){function e(e){this.type=r.Syntax.ExportAllDeclaration,this.source=e}return e}();t.ExportAllDeclaration=S;var E=function(){function e(e){this.type=r.Syntax.ExportDefaultDeclaration,this.declaration=e}return e}();t.ExportDefaultDeclaration=E;var C=function(){function e(e,t,n){this.type=r.Syntax.ExportNamedDeclaration,this.declaration=e,this.specifiers=t,this.source=n}return e}();t.ExportNamedDeclaration=C;var A=function(){function e(e,t){
+this.type=r.Syntax.ExportSpecifier,this.exported=t,this.local=e}return e}();t.ExportSpecifier=A;var T=function(){function e(e){this.type=r.Syntax.ExpressionStatement,this.expression=e}return e}();t.ExpressionStatement=T;var O=function(){function e(e,t,n){this.type=r.Syntax.ForInStatement,this.left=e,this.right=t,this.body=n,this.each=!1}return e}();t.ForInStatement=O;var D=function(){function e(e,t,n){this.type=r.Syntax.ForOfStatement,this.left=e,this.right=t,this.body=n}return e}();t.ForOfStatement=D;var M=function(){function e(e,t,n,i){this.type=r.Syntax.ForStatement,this.init=e,this.test=t,this.update=n,this.body=i}return e}();t.ForStatement=M;var P=function(){function e(e,t,n,i){this.type=r.Syntax.FunctionDeclaration,this.id=e,this.params=t,this.body=n,this.generator=i,this.expression=!1}return e}();t.FunctionDeclaration=P;var I=function(){function e(e,t,n,i){this.type=r.Syntax.FunctionExpression,this.id=e,this.params=t,this.body=n,this.generator=i,this.expression=!1}return e}();t.FunctionExpression=I;var j=function(){function e(e){this.type=r.Syntax.Identifier,this.name=e}return e}();t.Identifier=j;var R=function(){function e(e,t,n){this.type=r.Syntax.IfStatement,this.test=e,this.consequent=t,this.alternate=n}return e}();t.IfStatement=R;var F=function(){function e(e,t){this.type=r.Syntax.ImportDeclaration,this.specifiers=e,this.source=t}return e}();t.ImportDeclaration=F;var B=function(){function e(e){this.type=r.Syntax.ImportDefaultSpecifier,this.local=e}return e}();t.ImportDefaultSpecifier=B;var N=function(){function e(e){this.type=r.Syntax.ImportNamespaceSpecifier,this.local=e}return e}();t.ImportNamespaceSpecifier=N;var z=function(){function e(e,t){this.type=r.Syntax.ImportSpecifier,this.local=e,this.imported=t}return e}();t.ImportSpecifier=z;var L=function(){function e(e,t){this.type=r.Syntax.LabeledStatement,this.label=e,this.body=t}return e}();t.LabeledStatement=L;var U=function(){function e(e,t){this.type=r.Syntax.Literal,this.value=e,this.raw=t}return e}();t.Literal=U;var q=function(){function e(e,t){this.type=r.Syntax.MetaProperty,this.meta=e,this.property=t}return e}();t.MetaProperty=q;var W=function(){function e(e,t,n,i,o){this.type=r.Syntax.MethodDefinition,this.key=e,this.computed=t,this.value=n,this.kind=i,this.static=o}return e}();t.MethodDefinition=W;var K=function(){function e(e,t){this.type=r.Syntax.NewExpression,this.callee=e,this.arguments=t}return e}();t.NewExpression=K;var V=function(){function e(e){this.type=r.Syntax.ObjectExpression,this.properties=e}return e}();t.ObjectExpression=V;var H=function(){function e(e){this.type=r.Syntax.ObjectPattern,this.properties=e}return e}();t.ObjectPattern=H;var J=function(){function e(e,t){this.type=r.Syntax.Program,this.body=e,this.sourceType=t}return e}();t.Program=J;var G=function(){function e(e,t,n,i,o,a){this.type=r.Syntax.Property,this.key=t,this.computed=n,this.value=i,this.kind=e,this.method=o,this.shorthand=a}return e}();t.Property=G;var X=function(){function e(e,t,n){this.type=r.Syntax.Literal,this.value=e,this.raw=t,this.regex=n}return e}();t.RegexLiteral=X;var Y=function(){function e(e){this.type=r.Syntax.RestElement,this.argument=e}return e}();t.RestElement=Y;var $=function(){function e(e){this.type=r.Syntax.ReturnStatement,this.argument=e}return e}();t.ReturnStatement=$;var Z=function(){function e(e){this.type=r.Syntax.SequenceExpression,this.expressions=e}return e}();t.SequenceExpression=Z;var Q=function(){function e(e){this.type=r.Syntax.SpreadElement,this.argument=e}return e}();t.SpreadElement=Q;var ee=function(){function e(e,t){this.type=r.Syntax.MemberExpression,this.computed=!1,this.object=e,this.property=t}return e}();t.StaticMemberExpression=ee;var te=function(){function e(){this.type=r.Syntax.Super}return e}();t.Super=te;var ne=function(){function e(e,t){this.type=r.Syntax.SwitchCase,this.test=e,this.consequent=t}return e}();t.SwitchCase=ne;var re=function(){function e(e,t){this.type=r.Syntax.SwitchStatement,this.discriminant=e,this.cases=t}return e}();t.SwitchStatement=re;var ie=function(){function e(e,t){this.type=r.Syntax.TaggedTemplateExpression,this.tag=e,this.quasi=t}return e}();t.TaggedTemplateExpression=ie;var oe=function(){function e(e,t){this.type=r.Syntax.TemplateElement,this.value=e,this.tail=t}return e}();t.TemplateElement=oe;var ae=function(){function e(e,t){this.type=r.Syntax.TemplateLiteral,this.quasis=e,this.expressions=t}return e}();t.TemplateLiteral=ae;var se=function(){function e(){this.type=r.Syntax.ThisExpression}return e}();t.ThisExpression=se;var ue=function(){function e(e){this.type=r.Syntax.ThrowStatement,this.argument=e}return e}();t.ThrowStatement=ue;var ce=function(){function e(e,t,n){this.type=r.Syntax.TryStatement,this.block=e,this.handler=t,this.finalizer=n}return e}();t.TryStatement=ce;var le=function(){function e(e,t){this.type=r.Syntax.UnaryExpression,this.operator=e,this.argument=t,this.prefix=!0}return e}();t.UnaryExpression=le;var pe=function(){function e(e,t,n){this.type=r.Syntax.UpdateExpression,this.operator=e,this.argument=t,this.prefix=n}return e}();t.UpdateExpression=pe;var fe=function(){function e(e,t){this.type=r.Syntax.VariableDeclaration,this.declarations=e,this.kind=t}return e}();t.VariableDeclaration=fe;var he=function(){function e(e,t){this.type=r.Syntax.VariableDeclarator,this.id=e,this.init=t}return e}();t.VariableDeclarator=he;var de=function(){function e(e,t){this.type=r.Syntax.WhileStatement,this.test=e,this.body=t}return e}();t.WhileStatement=de;var me=function(){function e(e,t){this.type=r.Syntax.WithStatement,this.object=e,this.body=t}return e}();t.WithStatement=me;var ye=function(){function e(e,t){this.type=r.Syntax.YieldExpression,this.argument=e,this.delegate=t}return e}();t.YieldExpression=ye},function(e,t,n){"use strict";function r(e){var t;switch(e.type){case l.JSXSyntax.JSXIdentifier:var n=e;t=n.name;break;case l.JSXSyntax.JSXNamespacedName:var i=e;t=r(i.namespace)+":"+r(i.name);break;case l.JSXSyntax.JSXMemberExpression:var o=e;t=r(o.object)+"."+r(o.property)}return t}var i,o=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},a=n(9),s=n(7),u=n(3),c=n(12),l=n(13),p=n(10),f=n(14);!function(e){e[e.Identifier=100]="Identifier",e[e.Text=101]="Text"}(i||(i={})),s.TokenName[i.Identifier]="JSXIdentifier",s.TokenName[i.Text]="JSXText";var h=function(e){function t(t,n,r){e.call(this,t,n,r)}return o(t,e),t.prototype.parsePrimaryExpression=function(){return this.match("<")?this.parseJSXRoot():e.prototype.parsePrimaryExpression.call(this)},t.prototype.startJSX=function(){this.scanner.index=this.startMarker.index,this.scanner.lineNumber=this.startMarker.lineNumber,this.scanner.lineStart=this.startMarker.lineStart},t.prototype.finishJSX=function(){this.nextToken()},t.prototype.reenterJSX=function(){this.startJSX(),this.expectJSX("}"),this.config.tokens&&this.tokens.pop()},t.prototype.createJSXNode=function(){return this.collectComments(),{index:this.scanner.index,line:this.scanner.lineNumber,column:this.scanner.index-this.scanner.lineStart}},t.prototype.createJSXChildNode=function(){return{index:this.scanner.index,line:this.scanner.lineNumber,column:this.scanner.index-this.scanner.lineStart}},t.prototype.scanXHTMLEntity=function(e){for(var t="&",n=!0,r=!1,i=!1,o=!1;!this.scanner.eof()&&n&&!r;){var s=this.scanner.source[this.scanner.index];if(s===e)break;if(r=";"===s,t+=s,++this.scanner.index,!r)switch(t.length){case 2:i="#"===s;break;case 3:i&&(o="x"===s,n=o||a.Character.isDecimalDigit(s.charCodeAt(0)),i=i&&!o);break;default:n=n&&!(i&&!a.Character.isDecimalDigit(s.charCodeAt(0))),n=n&&!(o&&!a.Character.isHexDigit(s.charCodeAt(0)))}}if(n&&r&&t.length>2){var u=t.substr(1,t.length-2);i&&u.length>1?t=String.fromCharCode(parseInt(u.substr(1),10)):o&&u.length>2?t=String.fromCharCode(parseInt("0"+u.substr(1),16)):i||o||!c.XHTMLEntities[u]||(t=c.XHTMLEntities[u])}return t},t.prototype.lexJSX=function(){var e=this.scanner.source.charCodeAt(this.scanner.index);if(60===e||62===e||47===e||58===e||61===e||123===e||125===e){var t=this.scanner.source[this.scanner.index++];return{type:s.Token.Punctuator,value:t,lineNumber:this.scanner.lineNumber,lineStart:this.scanner.lineStart,start:this.scanner.index-1,end:this.scanner.index}}if(34===e||39===e){for(var n=this.scanner.index,r=this.scanner.source[this.scanner.index++],o="";!this.scanner.eof();){var u=this.scanner.source[this.scanner.index++];if(u===r)break;o+="&"===u?this.scanXHTMLEntity(r):u}return{type:s.Token.StringLiteral,value:o,lineNumber:this.scanner.lineNumber,lineStart:this.scanner.lineStart,start:n,end:this.scanner.index}}if(46===e){var c=this.scanner.source.charCodeAt(this.scanner.index+1),l=this.scanner.source.charCodeAt(this.scanner.index+2),t=46===c&&46===l?"...":".",n=this.scanner.index;return this.scanner.index+=t.length,{type:s.Token.Punctuator,value:t,lineNumber:this.scanner.lineNumber,lineStart:this.scanner.lineStart,start:n,end:this.scanner.index}}if(96===e)return{type:s.Token.Template,lineNumber:this.scanner.lineNumber,lineStart:this.scanner.lineStart,start:this.scanner.index,end:this.scanner.index};if(a.Character.isIdentifierStart(e)&&92!==e){var n=this.scanner.index;for(++this.scanner.index;!this.scanner.eof();){var u=this.scanner.source.charCodeAt(this.scanner.index);if(a.Character.isIdentifierPart(u)&&92!==u)++this.scanner.index;else{if(45!==u)break;++this.scanner.index}}var p=this.scanner.source.slice(n,this.scanner.index);return{type:i.Identifier,value:p,lineNumber:this.scanner.lineNumber,lineStart:this.scanner.lineStart,start:n,end:this.scanner.index}}this.scanner.throwUnexpectedToken()},t.prototype.nextJSXToken=function(){this.collectComments(),this.startMarker.index=this.scanner.index,this.startMarker.lineNumber=this.scanner.lineNumber,this.startMarker.lineStart=this.scanner.lineStart;var e=this.lexJSX();return this.lastMarker.index=this.scanner.index,this.lastMarker.lineNumber=this.scanner.lineNumber,this.lastMarker.lineStart=this.scanner.lineStart,this.config.tokens&&this.tokens.push(this.convertToken(e)),e},t.prototype.nextJSXText=function(){this.startMarker.index=this.scanner.index,this.startMarker.lineNumber=this.scanner.lineNumber,this.startMarker.lineStart=this.scanner.lineStart;for(var e=this.scanner.index,t="";!this.scanner.eof();){var n=this.scanner.source[this.scanner.index];if("{"===n||"<"===n)break;++this.scanner.index,t+=n,a.Character.isLineTerminator(n.charCodeAt(0))&&(++this.scanner.lineNumber,"\r"===n&&"\n"===this.scanner.source[this.scanner.index]&&++this.scanner.index,this.scanner.lineStart=this.scanner.index)}this.lastMarker.index=this.scanner.index,this.lastMarker.lineNumber=this.scanner.lineNumber,this.lastMarker.lineStart=this.scanner.lineStart;var r={type:i.Text,value:t,lineNumber:this.scanner.lineNumber,lineStart:this.scanner.lineStart,start:e,end:this.scanner.index};return t.length>0&&this.config.tokens&&this.tokens.push(this.convertToken(r)),r},t.prototype.peekJSXToken=function(){var e=this.scanner.index,t=this.scanner.lineNumber,n=this.scanner.lineStart;this.scanner.scanComments();var r=this.lexJSX();return this.scanner.index=e,this.scanner.lineNumber=t,this.scanner.lineStart=n,r},t.prototype.expectJSX=function(e){var t=this.nextJSXToken();t.type===s.Token.Punctuator&&t.value===e||this.throwUnexpectedToken(t)},t.prototype.matchJSX=function(e){var t=this.peekJSXToken();return t.type===s.Token.Punctuator&&t.value===e},t.prototype.parseJSXIdentifier=function(){var e=this.createJSXNode(),t=this.nextJSXToken();return t.type!==i.Identifier&&this.throwUnexpectedToken(t),this.finalize(e,new f.JSXIdentifier(t.value))},t.prototype.parseJSXElementName=function(){var e=this.createJSXNode(),t=this.parseJSXIdentifier();if(this.matchJSX(":")){var n=t;this.expectJSX(":");var r=this.parseJSXIdentifier();t=this.finalize(e,new f.JSXNamespacedName(n,r))}else if(this.matchJSX("."))for(;this.matchJSX(".");){var i=t;this.expectJSX(".");var o=this.parseJSXIdentifier();t=this.finalize(e,new f.JSXMemberExpression(i,o))}return t},t.prototype.parseJSXAttributeName=function(){var e,t=this.createJSXNode(),n=this.parseJSXIdentifier();if(this.matchJSX(":")){var r=n;this.expectJSX(":");var i=this.parseJSXIdentifier();e=this.finalize(t,new f.JSXNamespacedName(r,i))}else e=n;return e},t.prototype.parseJSXStringLiteralAttribute=function(){var e=this.createJSXNode(),t=this.nextJSXToken();t.type!==s.Token.StringLiteral&&this.throwUnexpectedToken(t);var n=this.getTokenRaw(t);return this.finalize(e,new p.Literal(t.value,n))},t.prototype.parseJSXExpressionAttribute=function(){var e=this.createJSXNode();this.expectJSX("{"),this.finishJSX(),this.match("}")&&this.tolerateError("JSX attributes must only be assigned a non-empty expression");var t=this.parseAssignmentExpression();return this.reenterJSX(),this.finalize(e,new f.JSXExpressionContainer(t))},t.prototype.parseJSXAttributeValue=function(){return this.matchJSX("{")?this.parseJSXExpressionAttribute():this.matchJSX("<")?this.parseJSXElement():this.parseJSXStringLiteralAttribute()},t.prototype.parseJSXNameValueAttribute=function(){var e=this.createJSXNode(),t=this.parseJSXAttributeName(),n=null;return this.matchJSX("=")&&(this.expectJSX("="),n=this.parseJSXAttributeValue()),this.finalize(e,new f.JSXAttribute(t,n))},t.prototype.parseJSXSpreadAttribute=function(){var e=this.createJSXNode();this.expectJSX("{"),this.expectJSX("..."),this.finishJSX();var t=this.parseAssignmentExpression();return this.reenterJSX(),this.finalize(e,new f.JSXSpreadAttribute(t))},t.prototype.parseJSXAttributes=function(){for(var e=[];!this.matchJSX("/")&&!this.matchJSX(">");){var t=this.matchJSX("{")?this.parseJSXSpreadAttribute():this.parseJSXNameValueAttribute();e.push(t)}return e},t.prototype.parseJSXOpeningElement=function(){var e=this.createJSXNode();this.expectJSX("<");var t=this.parseJSXElementName(),n=this.parseJSXAttributes(),r=this.matchJSX("/");return r&&this.expectJSX("/"),this.expectJSX(">"),this.finalize(e,new f.JSXOpeningElement(t,r,n))},t.prototype.parseJSXBoundaryElement=function(){var e=this.createJSXNode();if(this.expectJSX("<"),this.matchJSX("/")){this.expectJSX("/");var t=this.parseJSXElementName();return this.expectJSX(">"),this.finalize(e,new f.JSXClosingElement(t))}var n=this.parseJSXElementName(),r=this.parseJSXAttributes(),i=this.matchJSX("/");return i&&this.expectJSX("/"),this.expectJSX(">"),this.finalize(e,new f.JSXOpeningElement(n,i,r))},t.prototype.parseJSXEmptyExpression=function(){var e=this.createJSXChildNode();return this.collectComments(),this.lastMarker.index=this.scanner.index,this.lastMarker.lineNumber=this.scanner.lineNumber,this.lastMarker.lineStart=this.scanner.lineStart,this.finalize(e,new f.JSXEmptyExpression)},t.prototype.parseJSXExpressionContainer=function(){var e=this.createJSXNode();this.expectJSX("{");var t;return this.matchJSX("}")?(t=this.parseJSXEmptyExpression(),this.expectJSX("}")):(this.finishJSX(),t=this.parseAssignmentExpression(),this.reenterJSX()),this.finalize(e,new f.JSXExpressionContainer(t))},t.prototype.parseJSXChildren=function(){for(var e=[];!this.scanner.eof();){var t=this.createJSXChildNode(),n=this.nextJSXText();if(n.start0))break;var a=this.finalize(e.node,new f.JSXElement(e.opening,e.children,e.closing));e=t.pop(),e.children.push(a)}}return e},t.prototype.parseJSXElement=function(){var e=this.createJSXNode(),t=this.parseJSXOpeningElement(),n=[],r=null;if(!t.selfClosing){var i=this.parseComplexJSXElement({node:e,opening:t,closing:r,children:n});n=i.children,r=i.closing}return this.finalize(e,new f.JSXElement(t,n,r))},t.prototype.parseJSXRoot=function(){this.config.tokens&&this.tokens.pop(),this.startJSX();var e=this.parseJSXElement();return this.finishJSX(),e},t}(u.Parser);t.JSXParser=h},function(e,t){"use strict";t.XHTMLEntities={quot:'"',amp:"&",apos:"'",gt:">",nbsp:" ",iexcl:"¡",cent:"¢",pound:"£",curren:"¤",yen:"¥",brvbar:"¦",sect:"§",uml:"¨",copy:"©",ordf:"ª",laquo:"«",not:"¬",shy:"",reg:"®",macr:"¯",deg:"°",plusmn:"±",sup2:"²",sup3:"³",acute:"´",micro:"µ",para:"¶",middot:"·",cedil:"¸",sup1:"¹",ordm:"º",raquo:"»",frac14:"¼",frac12:"½",frac34:"¾",iquest:"¿",Agrave:"À",Aacute:"Á",Acirc:"Â",Atilde:"Ã",Auml:"Ä",Aring:"Å",AElig:"Æ",Ccedil:"Ç",Egrave:"È",Eacute:"É",Ecirc:"Ê",Euml:"Ë",Igrave:"Ì",Iacute:"Í",Icirc:"Î",Iuml:"Ï",ETH:"Ð",Ntilde:"Ñ",Ograve:"Ò",Oacute:"Ó",Ocirc:"Ô",Otilde:"Õ",Ouml:"Ö",times:"×",Oslash:"Ø",Ugrave:"Ù",Uacute:"Ú",Ucirc:"Û",Uuml:"Ü",Yacute:"Ý",THORN:"Þ",szlig:"ß",agrave:"à",aacute:"á",acirc:"â",atilde:"ã",auml:"ä",aring:"å",aelig:"æ",ccedil:"ç",egrave:"è",eacute:"é",ecirc:"ê",euml:"ë",igrave:"ì",iacute:"í",icirc:"î",iuml:"ï",eth:"ð",ntilde:"ñ",ograve:"ò",oacute:"ó",ocirc:"ô",otilde:"õ",ouml:"ö",divide:"÷",oslash:"ø",ugrave:"ù",uacute:"ú",ucirc:"û",uuml:"ü",yacute:"ý",thorn:"þ",yuml:"ÿ",OElig:"Œ",oelig:"œ",Scaron:"Š",scaron:"š",Yuml:"Ÿ",fnof:"ƒ",circ:"ˆ",tilde:"˜",Alpha:"Α",Beta:"Β",Gamma:"Γ",Delta:"Δ",Epsilon:"Ε",Zeta:"Ζ",Eta:"Η",Theta:"Θ",Iota:"Ι",Kappa:"Κ",Lambda:"Λ",Mu:"Μ",Nu:"Ν",Xi:"Ξ",Omicron:"Ο",Pi:"Π",Rho:"Ρ",Sigma:"Σ",Tau:"Τ",Upsilon:"Υ",Phi:"Φ",Chi:"Χ",Psi:"Ψ",Omega:"Ω",alpha:"α",beta:"β",gamma:"γ",delta:"δ",epsilon:"ε",zeta:"ζ",eta:"η",theta:"θ",iota:"ι",kappa:"κ",lambda:"λ",mu:"μ",nu:"ν",xi:"ξ",omicron:"ο",pi:"π",rho:"ρ",sigmaf:"ς",sigma:"σ",tau:"τ",upsilon:"υ",phi:"φ",chi:"χ",psi:"ψ",omega:"ω",thetasym:"ϑ",upsih:"ϒ",piv:"ϖ",ensp:" ",emsp:" ",thinsp:" ",zwnj:"",zwj:"",lrm:"",rlm:"",ndash:"–",mdash:"—",lsquo:"‘",rsquo:"’",sbquo:"‚",ldquo:"“",rdquo:"”",bdquo:"„",dagger:"†",Dagger:"‡",bull:"•",hellip:"…",permil:"‰",prime:"′",Prime:"″",lsaquo:"‹",rsaquo:"›",oline:"‾",frasl:"⁄",euro:"€",image:"ℑ",weierp:"℘",real:"ℜ",trade:"™",alefsym:"ℵ",larr:"←",uarr:"↑",rarr:"→",darr:"↓",harr:"↔",crarr:"↵",lArr:"⇐",uArr:"⇑",rArr:"⇒",dArr:"⇓",hArr:"⇔",forall:"∀",part:"∂",exist:"∃",empty:"∅",nabla:"∇",isin:"∈",notin:"∉",ni:"∋",prod:"∏",sum:"∑",minus:"−",lowast:"∗",radic:"√",prop:"∝",infin:"∞",ang:"∠",and:"∧",or:"∨",cap:"∩",cup:"∪",int:"∫",there4:"∴",sim:"∼",cong:"≅",asymp:"≈",ne:"≠",equiv:"≡",le:"≤",ge:"≥",sub:"⊂",sup:"⊃",nsub:"⊄",sube:"⊆",supe:"⊇",oplus:"⊕",otimes:"⊗",perp:"⊥",sdot:"⋅",lceil:"⌈",rceil:"⌉",lfloor:"⌊",rfloor:"⌋",loz:"◊",spades:"♠",clubs:"♣",hearts:"♥",diams:"♦",lang:"⟨",rang:"⟩"}},function(e,t){"use strict";t.JSXSyntax={JSXAttribute:"JSXAttribute",JSXClosingElement:"JSXClosingElement",JSXElement:"JSXElement",JSXEmptyExpression:"JSXEmptyExpression",JSXExpressionContainer:"JSXExpressionContainer",JSXIdentifier:"JSXIdentifier",JSXMemberExpression:"JSXMemberExpression",JSXNamespacedName:"JSXNamespacedName",JSXOpeningElement:"JSXOpeningElement",JSXSpreadAttribute:"JSXSpreadAttribute",JSXText:"JSXText"}},function(e,t,n){"use strict";var r=n(13),i=function(){function e(e){this.type=r.JSXSyntax.JSXClosingElement,this.name=e}return e}();t.JSXClosingElement=i;var o=function(){function e(e,t,n){this.type=r.JSXSyntax.JSXElement,this.openingElement=e,this.children=t,this.closingElement=n}return e}();t.JSXElement=o;var a=function(){function e(){this.type=r.JSXSyntax.JSXEmptyExpression}return e}();t.JSXEmptyExpression=a;var s=function(){function e(e){this.type=r.JSXSyntax.JSXExpressionContainer,this.expression=e}return e}();t.JSXExpressionContainer=s;var u=function(){function e(e){this.type=r.JSXSyntax.JSXIdentifier,this.name=e}return e}();t.JSXIdentifier=u;var c=function(){function e(e,t){this.type=r.JSXSyntax.JSXMemberExpression,this.object=e,this.property=t}return e}();t.JSXMemberExpression=c;var l=function(){function e(e,t){this.type=r.JSXSyntax.JSXAttribute,this.name=e,this.value=t}return e}();t.JSXAttribute=l;var p=function(){function e(e,t){this.type=r.JSXSyntax.JSXNamespacedName,this.namespace=e,this.name=t}return e}();t.JSXNamespacedName=p;var f=function(){function e(e,t,n){this.type=r.JSXSyntax.JSXOpeningElement,this.name=e,this.selfClosing=t,this.attributes=n}return e}();t.JSXOpeningElement=f;var h=function(){function e(e){this.type=r.JSXSyntax.JSXSpreadAttribute,this.argument=e}return e}();t.JSXSpreadAttribute=h;var d=function(){function e(e,t){this.type=r.JSXSyntax.JSXText,this.value=e,this.raw=t}return e}();t.JSXText=d},function(e,t,n){"use strict";var r=n(8),i=n(6),o=n(7),a=function(){function e(){this.values=[],this.curly=this.paren=-1}return e.prototype.beforeFunctionExpression=function(e){return["(","{","[","in","typeof","instanceof","new","return","case","delete","throw","void","=","+=","-=","*=","**=","/=","%=","<<=",">>=",">>>=","&=","|=","^=",",","+","-","*","**","/","%","++","--","<<",">>",">>>","&","|","^","!","~","&&","||","?",":","===","==",">=","<=","<",">","!=","!=="].indexOf(e)>=0},e.prototype.isRegexStart=function(){var e=this.values[this.values.length-1],t=null!==e;switch(e){case"this":case"]":t=!1;break;case")":var n=this.values[this.paren-1];t="if"===n||"while"===n||"for"===n||"with"===n;break;case"}":if(t=!1,"function"===this.values[this.curly-3]){var r=this.values[this.curly-4];t=!!r&&!this.beforeFunctionExpression(r)}else if("function"===this.values[this.curly-4]){var i=this.values[this.curly-5];t=!i||!this.beforeFunctionExpression(i)}}return t},e.prototype.push=function(e){e.type===o.Token.Punctuator||e.type===o.Token.Keyword?("{"===e.value?this.curly=this.values.length:"("===e.value&&(this.paren=this.values.length),this.values.push(e.value)):this.values.push(null)},e}(),s=function(){function e(e,t){this.errorHandler=new i.ErrorHandler,this.errorHandler.tolerant=!!t&&("boolean"==typeof t.tolerant&&t.tolerant),this.scanner=new r.Scanner(e,this.errorHandler),this.scanner.trackComment=!!t&&("boolean"==typeof t.comment&&t.comment),this.trackRange=!!t&&("boolean"==typeof t.range&&t.range),this.trackLoc=!!t&&("boolean"==typeof t.loc&&t.loc),this.buffer=[],this.reader=new a}return e.prototype.errors=function(){return this.errorHandler.errors},e.prototype.getNextToken=function(){if(0===this.buffer.length){var e=this.scanner.scanComments();if(this.scanner.trackComment)for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"";if(h.List.isList(e))return e.some(function(e){return h.Map.isMap(e)&&e.get("in")===t})}function s(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(h.List.isList(e))return e.some(function(e){return h.Map.isMap(e)&&e.get("type")===t})}function u(e,t){var n=_(e).getIn(["paths"].concat(r(t)),(0,h.fromJS)({})),i=n.get("parameters")||new h.List,o=s(i,"file")?"multipart/form-data":a(i,"formData")?"application/x-www-form-urlencoded":n.get("consumes_value");return(0,h.fromJS)({requestContentType:o,responseContentType:n.get("produces_value")})}function c(e,t){return _(e).getIn(["paths"].concat(r(t),["consumes"]),(0,h.fromJS)({}))}function l(e){return h.Map.isMap(e)?e:new h.Map}Object.defineProperty(t,"__esModule",{value:!0}),t.validateBeforeExecute=t.canExecuteScheme=t.operationScheme=t.hasHost=t.allowTryItOutFor=t.requestFor=t.responseFor=t.requests=t.responses=t.taggedOperations=t.operationsWithTags=t.tagDetails=t.tags=t.operationsWithRootInherited=t.schemes=t.host=t.basePath=t.definitions=t.findDefinition=t.securityDefinitions=t.security=t.produces=t.consumes=t.operations=t.paths=t.semver=t.version=t.externalDocs=t.info=t.spec=t.specResolved=t.specJson=t.specSource=t.specStr=t.url=t.lastError=void 0,t.getParameter=i,t.parameterValues=o,t.parametersIncludeIn=a,t.parametersIncludeType=s,t.contentTypeValues=u,t.operationConsumes=c;var p=n(573),f=n(336),h=n(326),d="default",m=["get","put","post","delete","options","head","patch"],y=function(e){return e||(0,h.Map)()},v=(t.lastError=(0,p.createSelector)(y,function(e){return e.get("lastError")}),t.url=(0,p.createSelector)(y,function(e){return e.get("url")}),t.specStr=(0,p.createSelector)(y,function(e){return e.get("spec")||""}),t.specSource=(0,p.createSelector)(y,function(e){return e.get("specSource")||"not-editor"}),t.specJson=(0,p.createSelector)(y,function(e){return e.get("json",(0,h.Map)())})),g=t.specResolved=(0,p.createSelector)(y,function(e){return e.get("resolved",(0,h.Map)())}),_=t.spec=function(e){var t=g(e);return t.count()<1&&(t=v(e)),t},b=t.info=(0,p.createSelector)(_,function(e){return l(e&&e.get("info"))}),w=(t.externalDocs=(0,p.createSelector)(_,function(e){return l(e&&e.get("externalDocs"))}),t.version=(0,p.createSelector)(b,function(e){return e&&e.get("version")})),x=(t.semver=(0,p.createSelector)(w,function(e){return/v?([0-9]*)\.([0-9]*)\.([0-9]*)/i.exec(e).slice(1)}),t.paths=(0,p.createSelector)(_,function(e){return e.get("paths")})),k=t.operations=(0,p.createSelector)(x,function(e){if(!e||e.size<1)return(0,h.List)();var t=(0,h.List)();return e&&e.forEach?(e.forEach(function(e,n){return e&&e.forEach?void e.forEach(function(e,r){m.indexOf(r)!==-1&&(t=t.push((0,h.fromJS)({path:n,method:r,operation:e,id:r+"-"+n})))}):{}}),t):(0,h.List)()}),S=t.consumes=(0,p.createSelector)(_,function(e){return(0,h.Set)(e.get("consumes"))}),E=t.produces=(0,p.createSelector)(_,function(e){return(0,h.Set)(e.get("produces"))}),C=(t.security=(0,p.createSelector)(_,function(e){return e.get("security",(0,h.List)())}),t.securityDefinitions=(0,p.createSelector)(_,function(e){return e.get("securityDefinitions")}),t.findDefinition=function(e,t){return g(e).getIn(["definitions",t],null)},t.definitions=(0,p.createSelector)(_,function(e){return e.get("definitions")||(0,h.Map)()}),t.basePath=(0,p.createSelector)(_,function(e){return e.get("basePath")}),t.host=(0,p.createSelector)(_,function(e){return e.get("host")}),t.schemes=(0,p.createSelector)(_,function(e){return e.get("schemes",(0,h.Map)())}),t.operationsWithRootInherited=(0,p.createSelector)(k,S,E,function(e,t,n){return e.map(function(e){return e.update("operation",function(e){if(e){if(!h.Map.isMap(e))return;return e.withMutations(function(e){return e.get("consumes")||e.update("consumes",function(e){return(0,h.Set)(e).merge(t);
+}),e.get("produces")||e.update("produces",function(e){return(0,h.Set)(e).merge(n)}),e})}return(0,h.Map)()})})})),A=t.tags=(0,p.createSelector)(_,function(e){return e.get("tags",(0,h.List)())}),T=t.tagDetails=function(e,t){var n=A(e)||(0,h.List)();return n.filter(h.Map.isMap).find(function(e){return e.get("name")===t},(0,h.Map)())},O=t.operationsWithTags=(0,p.createSelector)(C,function(e){return e.reduce(function(e,t){var n=(0,h.Set)(t.getIn(["operation","tags"]));return n.count()<1?e.update(d,(0,h.List)(),function(e){return e.push(t)}):n.reduce(function(e,n){return e.update(n,(0,h.List)(),function(e){return e.push(t)})},e)},(0,h.Map)())}),D=(t.taggedOperations=function(e){return function(t){var n=t.getConfigs,r=n(),i=r.operationsSorter;return O(e).map(function(t,n){var r="function"==typeof i?i:f.sorters.operationsSorter[i],o=r?t.sort(r):t;return(0,h.Map)({tagDetails:T(e,n),operations:o})})}},t.responses=(0,p.createSelector)(y,function(e){return e.get("responses",(0,h.Map)())})),M=t.requests=(0,p.createSelector)(y,function(e){return e.get("requests",(0,h.Map)())}),P=(t.responseFor=function(e,t,n){return D(e).getIn([t,n],null)},t.requestFor=function(e,t,n){return M(e).getIn([t,n],null)},t.allowTryItOutFor=function(){return!0},t.hasHost=(0,p.createSelector)(_,function(e){var t=e.get("host");return"string"==typeof t&&t.length>0&&"/"!==t[0]}),t.operationScheme=function(e,t,n){var r=e.get("url"),i=r.match(/^([a-z][a-z0-9+\-.]*):/),o=Array.isArray(i)?i[1]:null;return e.getIn(["scheme",t,n])||e.getIn(["scheme","_defaultScheme"])||o||""});t.canExecuteScheme=function(e,t,n){return["http","https"].indexOf(P(e,t,n))>-1},t.validateBeforeExecute=function(e,t){var n=_(e).getIn(["paths"].concat(r(t),["parameters"]),(0,h.fromJS)([])),i=!0;return n.forEach(function(e){var t=e.get("errors");t&&t.count()&&(i=!1)}),i}},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.updateSpec=function(e,t){var n=t.specActions;return function(){e.apply(void 0,arguments),n.parseToJson.apply(n,arguments)}},t.updateJsonSpec=function(e,t){var n=t.specActions;return function(){e.apply(void 0,arguments),n.resolveSpec.apply(n,arguments)}},t.executeRequest=function(e,t){var n=t.specActions;return function(t){return n.logRequest(t),e(t)}}},function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=e.getComponents,n=e.getStore,r=e.getSystem,i=o.getComponent,s=o.render,u=o.makeMappedContainer,c=(0,a.memoize)(i.bind(null,r,n,t)),l=(0,a.memoize)(u.bind(null,r,n,c,t));return{rootInjects:{getComponent:c,makeMappedContainer:l,render:s.bind(null,r,n,i,t)}}};var i=n(619),o=r(i),a=n(336)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0}),t.getComponent=t.render=t.makeMappedContainer=void 0;var s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u=Object.assign||function(e){for(var t=1;t1){for(var y=Array(m),v=0;v1){for(var _=Array(g),b=0;b>"),A={array:a("array"),bool:a("boolean"),func:a("function"),number:a("number"),object:a("object"),string:a("string"),symbol:a("symbol"),any:s(),arrayOf:u,element:c(),instanceOf:l,node:d(),objectOf:f,oneOf:p,oneOfType:h,shape:m};i.prototype=Error.prototype,e.exports=A},function(e,t){"use strict";var n="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=n},function(e,t){"use strict";e.exports="15.4.2"},function(e,t,n){"use strict";function r(e){return o.isValidElement(e)?void 0:i("143"),e}var i=n(625),o=n(627);n(626);e.exports=r},function(e,t,n){"use strict";e.exports=n(648)},function(e,t,n){"use strict";var r=n(649),i=n(653),o=n(775),a=n(674),s=n(671),u=n(780),c=n(781),l=n(782),p=n(783);n(629);i.inject();var f={findDOMNode:c,render:o.render,unmountComponentAtNode:o.unmountComponentAtNode,version:u,unstable_batchedUpdates:s.batchedUpdates,unstable_renderSubtreeIntoContainer:p};"undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject&&__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ComponentTree:{getClosestInstanceFromNode:r.getClosestInstanceFromNode,getNodeFromInstance:function(e){return e._renderedComponent&&(e=l(e)),e?r.getNodeFromInstance(e):null}},Mount:o,Reconciler:a});e.exports=f},function(e,t,n){"use strict";function r(e,t){return 1===e.nodeType&&e.getAttribute(d)===String(t)||8===e.nodeType&&e.nodeValue===" react-text: "+t+" "||8===e.nodeType&&e.nodeValue===" react-empty: "+t+" "}function i(e){for(var t;t=e._renderedComponent;)e=t;return e}function o(e,t){var n=i(e);n._hostNode=t,t[y]=n}function a(e){var t=e._hostNode;t&&(delete t[y],e._hostNode=null)}function s(e,t){if(!(e._flags&m.hasCachedChildNodes)){var n=e._renderedChildren,a=t.firstChild;e:for(var s in n)if(n.hasOwnProperty(s)){var u=n[s],c=i(u)._domID;if(0!==c){for(;null!==a;a=a.nextSibling)if(r(a,c)){o(u,a);continue e}p("32",c)}}e._flags|=m.hasCachedChildNodes}}function u(e){if(e[y])return e[y];for(var t=[];!e[y];){if(t.push(e),!e.parentNode)return null;e=e.parentNode}for(var n,r;e&&(r=e[y]);e=t.pop())n=r,t.length&&s(r,e);return n}function c(e){var t=u(e);return null!=t&&t._hostNode===e?t:null}function l(e){if(void 0===e._hostNode?p("33"):void 0,e._hostNode)return e._hostNode;for(var t=[];!e._hostNode;)t.push(e),e._hostParent?void 0:p("34"),e=e._hostParent;for(;t.length;e=t.pop())s(e,e._hostNode);return e._hostNode}var p=n(650),f=n(651),h=n(652),d=(n(626),f.ID_ATTRIBUTE_NAME),m=h,y="__reactInternalInstance$"+Math.random().toString(36).slice(2),v={getClosestInstanceFromNode:u,getInstanceFromNode:c,getNodeFromInstance:l,precacheChildNodes:s,precacheNode:o,uncacheNode:a};e.exports=v},625,function(e,t,n){"use strict";function r(e,t){return(e&t)===t}var i=n(650),o=(n(626),{MUST_USE_PROPERTY:1,HAS_BOOLEAN_VALUE:4,HAS_NUMERIC_VALUE:8,HAS_POSITIVE_NUMERIC_VALUE:24,HAS_OVERLOADED_BOOLEAN_VALUE:32,injectDOMPropertyConfig:function(e){var t=o,n=e.Properties||{},a=e.DOMAttributeNamespaces||{},u=e.DOMAttributeNames||{},c=e.DOMPropertyNames||{},l=e.DOMMutationMethods||{};e.isCustomAttribute&&s._isCustomAttributeFunctions.push(e.isCustomAttribute);for(var p in n){s.properties.hasOwnProperty(p)?i("48",p):void 0;var f=p.toLowerCase(),h=n[p],d={attributeName:f,attributeNamespace:null,propertyName:p,mutationMethod:null,mustUseProperty:r(h,t.MUST_USE_PROPERTY),hasBooleanValue:r(h,t.HAS_BOOLEAN_VALUE),hasNumericValue:r(h,t.HAS_NUMERIC_VALUE),hasPositiveNumericValue:r(h,t.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:r(h,t.HAS_OVERLOADED_BOOLEAN_VALUE)};if(d.hasBooleanValue+d.hasNumericValue+d.hasOverloadedBooleanValue<=1?void 0:i("50",p),u.hasOwnProperty(p)){var m=u[p];d.attributeName=m}a.hasOwnProperty(p)&&(d.attributeNamespace=a[p]),c.hasOwnProperty(p)&&(d.propertyName=c[p]),l.hasOwnProperty(p)&&(d.mutationMethod=l[p]),s.properties[p]=d}}}),a=":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",s={ID_ATTRIBUTE_NAME:"data-reactid",ROOT_ATTRIBUTE_NAME:"data-reactroot",ATTRIBUTE_NAME_START_CHAR:a,ATTRIBUTE_NAME_CHAR:a+"\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(e){for(var t=0;t8&&w<=11),S=32,E=String.fromCharCode(S),C={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["topCompositionEnd","topKeyPress","topTextInput","topPaste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:["topBlur","topCompositionEnd","topKeyDown","topKeyPress","topKeyUp","topMouseDown"]},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},dependencies:["topBlur","topCompositionStart","topKeyDown","topKeyPress","topKeyUp","topMouseDown"]},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:["topBlur","topCompositionUpdate","topKeyDown","topKeyPress","topKeyUp","topMouseDown"]}},A=!1,T=null,O={eventTypes:C,extractEvents:function(e,t,n,r){return[c(e,t,n,r),f(e,t,n,r)]}};e.exports=O},function(e,t,n){"use strict";function r(e,t,n){var r=t.dispatchConfig.phasedRegistrationNames[n];return v(e,r)}function i(e,t,n){var i=r(e,n,t);i&&(n._dispatchListeners=m(n._dispatchListeners,i),n._dispatchInstances=m(n._dispatchInstances,e))}function o(e){e&&e.dispatchConfig.phasedRegistrationNames&&d.traverseTwoPhase(e._targetInst,i,e)}function a(e){if(e&&e.dispatchConfig.phasedRegistrationNames){var t=e._targetInst,n=t?d.getParentInstance(t):null;d.traverseTwoPhase(n,i,e)}}function s(e,t,n){if(n&&n.dispatchConfig.registrationName){var r=n.dispatchConfig.registrationName,i=v(e,r);i&&(n._dispatchListeners=m(n._dispatchListeners,i),n._dispatchInstances=m(n._dispatchInstances,e))}}function u(e){e&&e.dispatchConfig.registrationName&&s(e._targetInst,null,e)}function c(e){y(e,o)}function l(e){y(e,a)}function p(e,t,n,r){d.traverseEnterLeave(n,r,s,e,t)}function f(e){y(e,u)}var h=n(657),d=n(659),m=n(661),y=n(662),v=(n(629),h.getListener),g={accumulateTwoPhaseDispatches:c,accumulateTwoPhaseDispatchesSkipTarget:l,accumulateDirectDispatches:f,accumulateEnterLeaveDispatches:p};e.exports=g},function(e,t,n){"use strict";function r(e){return"button"===e||"input"===e||"select"===e||"textarea"===e}function i(e,t,n){switch(e){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":return!(!n.disabled||!r(t));default:return!1}}var o=n(650),a=n(658),s=n(659),u=n(660),c=n(661),l=n(662),p=(n(626),{}),f=null,h=function(e,t){e&&(s.executeDispatchesInOrder(e,t),e.isPersistent()||e.constructor.release(e))},d=function(e){return h(e,!0)},m=function(e){return h(e,!1)},y=function(e){return"."+e._rootNodeID},v={injection:{injectEventPluginOrder:a.injectEventPluginOrder,injectEventPluginsByName:a.injectEventPluginsByName},putListener:function(e,t,n){"function"!=typeof n?o("94",t,typeof n):void 0;var r=y(e),i=p[t]||(p[t]={});i[r]=n;var s=a.registrationNameModules[t];s&&s.didPutListener&&s.didPutListener(e,t,n)},getListener:function(e,t){var n=p[t];if(i(t,e._currentElement.type,e._currentElement.props))return null;var r=y(e);return n&&n[r]},deleteListener:function(e,t){var n=a.registrationNameModules[t];n&&n.willDeleteListener&&n.willDeleteListener(e,t);var r=p[t];if(r){var i=y(e);delete r[i]}},deleteAllListeners:function(e){var t=y(e);for(var n in p)if(p.hasOwnProperty(n)&&p[n][t]){var r=a.registrationNameModules[n];r&&r.willDeleteListener&&r.willDeleteListener(e,n),delete p[n][t]}},extractEvents:function(e,t,n,r){for(var i,o=a.plugins,s=0;s-1?void 0:a("96",e),!c.plugins[n]){t.extractEvents?void 0:a("97",e),c.plugins[n]=t;var r=t.eventTypes;for(var o in r)i(r[o],t,o)?void 0:a("98",o,e)}}}function i(e,t,n){c.eventNameDispatchConfigs.hasOwnProperty(n)?a("99",n):void 0,c.eventNameDispatchConfigs[n]=e;var r=e.phasedRegistrationNames;if(r){for(var i in r)if(r.hasOwnProperty(i)){var s=r[i];o(s,t,n)}return!0}return!!e.registrationName&&(o(e.registrationName,t,n),!0)}function o(e,t,n){c.registrationNameModules[e]?a("100",e):void 0,c.registrationNameModules[e]=t,c.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var a=n(650),s=(n(626),null),u={},c={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},possibleRegistrationNames:null,injectEventPluginOrder:function(e){s?a("101"):void 0,s=Array.prototype.slice.call(e),r()},injectEventPluginsByName:function(e){var t=!1;for(var n in e)if(e.hasOwnProperty(n)){var i=e[n];u.hasOwnProperty(n)&&u[n]===i||(u[n]?a("102",n):void 0,u[n]=i,t=!0)}t&&r()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return c.registrationNameModules[t.registrationName]||null;if(void 0!==t.phasedRegistrationNames){var n=t.phasedRegistrationNames;for(var r in n)if(n.hasOwnProperty(r)){var i=c.registrationNameModules[n[r]];if(i)return i}}return null},_resetEventPlugins:function(){s=null;for(var e in u)u.hasOwnProperty(e)&&delete u[e];c.plugins.length=0;var t=c.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=c.registrationNameModules;for(var i in r)r.hasOwnProperty(i)&&delete r[i]}};e.exports=c},function(e,t,n){"use strict";function r(e){return"topMouseUp"===e||"topTouchEnd"===e||"topTouchCancel"===e}function i(e){return"topMouseMove"===e||"topTouchMove"===e}function o(e){return"topMouseDown"===e||"topTouchStart"===e}function a(e,t,n,r){var i=e.type||"unknown-event";e.currentTarget=v.getNodeFromInstance(r),t?m.invokeGuardedCallbackWithCatch(i,n,e):m.invokeGuardedCallback(i,n,e),e.currentTarget=null}function s(e,t){var n=e._dispatchListeners,r=e._dispatchInstances;if(Array.isArray(n))for(var i=0;i1?1-t:void 0;return this._fallbackText=i.slice(e,s),this._fallbackText}}),o.addPoolingTo(r),e.exports=r},[1502,650],function(e,t,n){"use strict";function r(){return!o&&i.canUseDOM&&(o="textContent"in document.documentElement?"textContent":"innerText"),o}var i=n(663),o=null;e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(668),o={data:null};i.augmentClass(r,o),e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){this.dispatchConfig=e,this._targetInst=t,this.nativeEvent=n;var i=this.constructor.Interface;for(var o in i)if(i.hasOwnProperty(o)){var s=i[o];s?this[o]=s(n):"target"===o?this.target=r:this[o]=n[o]}var u=null!=n.defaultPrevented?n.defaultPrevented:n.returnValue===!1;return u?this.isDefaultPrevented=a.thatReturnsTrue:this.isDefaultPrevented=a.thatReturnsFalse,this.isPropagationStopped=a.thatReturnsFalse,this}var i=n(622),o=n(665),a=n(630),s=(n(629),"function"==typeof Proxy,["dispatchConfig","_targetInst","nativeEvent","isDefaultPrevented","isPropagationStopped","_dispatchListeners","_dispatchInstances"]),u={type:null,target:null,currentTarget:a.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null};i(r.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=a.thatReturnsTrue)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=a.thatReturnsTrue)},persist:function(){this.isPersistent=a.thatReturnsTrue},isPersistent:a.thatReturnsFalse,destructor:function(){var e=this.constructor.Interface;for(var t in e)this[t]=null;for(var n=0;n8));var I=!1;b.canUseDOM&&(I=E("input")&&(!document.documentMode||document.documentMode>11));var j={get:function(){return M.get.call(this)},set:function(e){D=""+e,M.set.call(this,e)}},R={eventTypes:A,extractEvents:function(e,t,n,i){var o,a,s=t?w.getNodeFromInstance(t):window;if(r(s)?P?o=u:a=c:C(s)?I?o=h:(o=m,a=d):y(s)&&(o=v),o){var l=o(e,t);if(l){var p=k.getPooled(A.change,l,n,i);return p.type="change",_.accumulateTwoPhaseDispatches(p),p}}a&&a(e,s,t)}};e.exports=R},function(e,t,n){"use strict";function r(){A.ReactReconcileTransaction&&w?void 0:l("123")}function i(){this.reinitializeTransaction(),this.dirtyComponentsLength=null,this.callbackQueue=f.getPooled(),this.reconcileTransaction=A.ReactReconcileTransaction.getPooled(!0)}function o(e,t,n,i,o,a){return r(),w.batchedUpdates(e,t,n,i,o,a)}function a(e,t){return e._mountOrder-t._mountOrder}function s(e){var t=e.dirtyComponentsLength;t!==v.length?l("124",t,v.length):void 0,v.sort(a),g++;for(var n=0;n]/,u=n(694),c=u(function(e,t){if(e.namespaceURI!==o.svg||"innerHTML"in e)e.innerHTML=t;else{r=r||document.createElement("div"),r.innerHTML="";for(var n=r.firstChild;n.firstChild;)e.appendChild(n.firstChild)}});if(i.canUseDOM){var l=document.createElement("div");l.innerHTML=" ",""===l.innerHTML&&(c=function(e,t){if(e.parentNode&&e.parentNode.replaceChild(e,e),a.test(t)||"<"===t[0]&&s.test(t)){e.innerHTML=String.fromCharCode(65279)+t;var n=e.firstChild;1===n.data.length?e.removeChild(n):n.deleteData(0,1)}else e.innerHTML=t}),l=null}e.exports=c},function(e,t){"use strict";var n=function(e){return"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(t,n,r,i){MSApp.execUnsafeLocalFunction(function(){return e(t,n,r,i)})}:e};e.exports=n},function(e,t,n){"use strict";var r=n(663),i=n(696),o=n(693),a=function(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t};r.canUseDOM&&("textContent"in document.documentElement||(a=function(e,t){return 3===e.nodeType?void(e.nodeValue=t):void o(e,i(t))})),e.exports=a},function(e,t){"use strict";function n(e){var t=""+e,n=i.exec(t);if(!n)return t;var r,o="",a=0,s=0;for(a=n.index;a]/;e.exports=r},function(e,t,n){"use strict";var r=n(650),i=n(691),o=n(663),a=n(698),s=n(630),u=(n(626),{dangerouslyReplaceNodeWithMarkup:function(e,t){if(o.canUseDOM?void 0:r("56"),t?void 0:r("57"),"HTML"===e.nodeName?r("58"):void 0,"string"==typeof t){var n=a(t,s)[0];e.parentNode.replaceChild(n,e)}else i.replaceChildWithTree(e,t)}});e.exports=u},function(e,t,n){"use strict";function r(e){var t=e.match(l);return t&&t[1].toLowerCase()}function i(e,t){var n=c;c?void 0:u(!1);var i=r(e),o=i&&s(i);if(o){n.innerHTML=o[1]+e+o[2];for(var l=o[0];l--;)n=n.lastChild}else n.innerHTML=e;var p=n.getElementsByTagName("script");p.length&&(t?void 0:u(!1),a(p).forEach(t));for(var f=Array.from(n.childNodes);n.lastChild;)n.removeChild(n.lastChild);return f}var o=n(663),a=n(699),s=n(700),u=n(626),c=o.canUseDOM?document.createElement("div"):null,l=/^\s*<(\w+)/;e.exports=i},function(e,t,n){"use strict";function r(e){var t=e.length;if(Array.isArray(e)||"object"!=typeof e&&"function"!=typeof e?a(!1):void 0,"number"!=typeof t?a(!1):void 0,0===t||t-1 in e?void 0:a(!1),"function"==typeof e.callee?a(!1):void 0,e.hasOwnProperty)try{return Array.prototype.slice.call(e)}catch(e){}for(var n=Array(t),r=0;r":a.innerHTML="<"+e+">"+e+">",s[e]=!a.firstChild),s[e]?f[e]:null}var i=n(663),o=n(626),a=i.canUseDOM?document.createElement("div"):null,s={},u=[1,'"],c=[1,""],l=[3,""],p=[1,'"],f={"*":[1,"?","
"],area:[1,""],col:[2,""],legend:[1,""],param:[1,""],tr:[2,""],optgroup:u,option:u,caption:c,colgroup:c,tbody:c,tfoot:c,thead:c,td:l,th:l},h=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];h.forEach(function(e){f[e]=p,s[e]=!0}),e.exports=r},function(e,t,n){"use strict";var r=n(690),i=n(649),o={dangerouslyProcessChildrenUpdates:function(e,t){var n=i.getNodeFromInstance(e);r.processUpdates(n,t)}};e.exports=o},function(e,t,n){"use strict";function r(e){if(e){var t=e._currentElement._owner||null;if(t){var n=t.getName();if(n)return" This DOM node was rendered by `"+n+"`."}}return""}function i(e,t){t&&(G[e._tag]&&(null!=t.children||null!=t.dangerouslySetInnerHTML?m("137",e._tag,e._currentElement._owner?" Check the render method of "+e._currentElement._owner.getName()+".":""):void 0),null!=t.dangerouslySetInnerHTML&&(null!=t.children?m("60"):void 0,"object"==typeof t.dangerouslySetInnerHTML&&q in t.dangerouslySetInnerHTML?void 0:m("61")),null!=t.style&&"object"!=typeof t.style?m("62",r(e)):void 0)}function o(e,t,n,r){if(!(r instanceof I)){var i=e._hostContainerInfo,o=i._node&&i._node.nodeType===K,s=o?i._node:i._ownerDocument;N(t,s),r.getReactMountReady().enqueue(a,{inst:e,registrationName:t,listener:n})}}function a(){var e=this;k.putListener(e.inst,e.registrationName,e.listener)}function s(){var e=this;T.postMountWrapper(e)}function u(){var e=this;M.postMountWrapper(e)}function c(){var e=this;O.postMountWrapper(e)}function l(){var e=this;e._rootNodeID?void 0:m("63");var t=B(e);switch(t?void 0:m("64"),e._tag){case"iframe":case"object":e._wrapperState.listeners=[E.trapBubbledEvent("topLoad","load",t)];break;case"video":case"audio":e._wrapperState.listeners=[];for(var n in V)V.hasOwnProperty(n)&&e._wrapperState.listeners.push(E.trapBubbledEvent(n,V[n],t));break;case"source":e._wrapperState.listeners=[E.trapBubbledEvent("topError","error",t)];break;case"img":e._wrapperState.listeners=[E.trapBubbledEvent("topError","error",t),E.trapBubbledEvent("topLoad","load",t)];break;case"form":e._wrapperState.listeners=[E.trapBubbledEvent("topReset","reset",t),E.trapBubbledEvent("topSubmit","submit",t)];break;case"input":case"select":case"textarea":e._wrapperState.listeners=[E.trapBubbledEvent("topInvalid","invalid",t)]}}function p(){D.postUpdateWrapper(this)}function f(e){$.call(Y,e)||(X.test(e)?void 0:m("65",e),Y[e]=!0)}function h(e,t){return e.indexOf("-")>=0||null!=t.is}function d(e){var t=e.type;f(t),this._currentElement=e,this._tag=t.toLowerCase(),this._namespaceURI=null,this._renderedChildren=null,this._previousStyle=null,this._previousStyleCopy=null,this._hostNode=null,this._hostParent=null,this._rootNodeID=0,this._domID=0,this._hostContainerInfo=null,this._wrapperState=null,this._topLevelWrapper=null,this._flags=0}var m=n(650),y=n(622),v=n(703),g=n(705),_=n(691),b=n(692),w=n(651),x=n(713),k=n(657),S=n(658),E=n(715),C=n(652),A=n(649),T=n(718),O=n(721),D=n(722),M=n(723),P=(n(677),n(724)),I=n(742),j=(n(630),n(696)),R=(n(626),n(680),n(731),n(745),n(629),C),F=k.deleteListener,B=A.getNodeFromInstance,N=E.listenTo,z=S.registrationNameModules,L={string:!0,number:!0},U="style",q="__html",W={children:null,dangerouslySetInnerHTML:null,suppressContentEditableWarning:null},K=11,V={topAbort:"abort",topCanPlay:"canplay",topCanPlayThrough:"canplaythrough",topDurationChange:"durationchange",topEmptied:"emptied",topEncrypted:"encrypted",topEnded:"ended",topError:"error",topLoadedData:"loadeddata",topLoadedMetadata:"loadedmetadata",topLoadStart:"loadstart",topPause:"pause",topPlay:"play",topPlaying:"playing",topProgress:"progress",topRateChange:"ratechange",topSeeked:"seeked",topSeeking:"seeking",topStalled:"stalled",topSuspend:"suspend",topTimeUpdate:"timeupdate",topVolumeChange:"volumechange",topWaiting:"waiting"},H={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},J={listing:!0,pre:!0,textarea:!0},G=y({menuitem:!0},H),X=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,Y={},$={}.hasOwnProperty,Z=1;d.displayName="ReactDOMComponent",d.Mixin={mountComponent:function(e,t,n,r){this._rootNodeID=Z++,this._domID=n._idCounter++,this._hostParent=t,this._hostContainerInfo=n;var o=this._currentElement.props;switch(this._tag){case"audio":case"form":case"iframe":case"img":case"link":case"object":case"source":case"video":this._wrapperState={listeners:null},e.getReactMountReady().enqueue(l,this);break;case"input":T.mountWrapper(this,o,t),o=T.getHostProps(this,o),e.getReactMountReady().enqueue(l,this);break;case"option":O.mountWrapper(this,o,t),o=O.getHostProps(this,o);break;case"select":D.mountWrapper(this,o,t),o=D.getHostProps(this,o),e.getReactMountReady().enqueue(l,this);break;case"textarea":M.mountWrapper(this,o,t),o=M.getHostProps(this,o),e.getReactMountReady().enqueue(l,this)}i(this,o);var a,p;null!=t?(a=t._namespaceURI,p=t._tag):n._tag&&(a=n._namespaceURI,p=n._tag),(null==a||a===b.svg&&"foreignobject"===p)&&(a=b.html),a===b.html&&("svg"===this._tag?a=b.svg:"math"===this._tag&&(a=b.mathml)),this._namespaceURI=a;var f;if(e.useCreateElement){var h,d=n._ownerDocument;if(a===b.html)if("script"===this._tag){var m=d.createElement("div"),y=this._currentElement.type;m.innerHTML="<"+y+">"+y+">",h=m.removeChild(m.firstChild)}else h=o.is?d.createElement(this._currentElement.type,o.is):d.createElement(this._currentElement.type);else h=d.createElementNS(a,this._currentElement.type);A.precacheNode(this,h),this._flags|=R.hasCachedChildNodes,this._hostParent||x.setAttributeForRoot(h),this._updateDOMProperties(null,o,e);var g=_(h);this._createInitialChildren(e,o,r,g),f=g}else{var w=this._createOpenTagMarkupAndPutListeners(e,o),k=this._createContentMarkup(e,o,r);f=!k&&H[this._tag]?w+"/>":w+">"+k+""+this._currentElement.type+">"}switch(this._tag){case"input":e.getReactMountReady().enqueue(s,this),o.autoFocus&&e.getReactMountReady().enqueue(v.focusDOMComponent,this);break;case"textarea":e.getReactMountReady().enqueue(u,this),o.autoFocus&&e.getReactMountReady().enqueue(v.focusDOMComponent,this);break;case"select":o.autoFocus&&e.getReactMountReady().enqueue(v.focusDOMComponent,this);break;case"button":o.autoFocus&&e.getReactMountReady().enqueue(v.focusDOMComponent,this);break;case"option":e.getReactMountReady().enqueue(c,this)}return f},_createOpenTagMarkupAndPutListeners:function(e,t){var n="<"+this._currentElement.type;for(var r in t)if(t.hasOwnProperty(r)){var i=t[r];if(null!=i)if(z.hasOwnProperty(r))i&&o(this,r,i,e);else{r===U&&(i&&(i=this._previousStyleCopy=y({},t.style)),i=g.createMarkupForStyles(i,this));var a=null;null!=this._tag&&h(this._tag,t)?W.hasOwnProperty(r)||(a=x.createMarkupForCustomAttribute(r,i)):a=x.createMarkupForProperty(r,i),a&&(n+=" "+a)}}return e.renderToStaticMarkup?n:(this._hostParent||(n+=" "+x.createMarkupForRoot()),n+=" "+x.createMarkupForID(this._domID))},_createContentMarkup:function(e,t,n){var r="",i=t.dangerouslySetInnerHTML;if(null!=i)null!=i.__html&&(r=i.__html);else{var o=L[typeof t.children]?t.children:null,a=null!=o?null:t.children;if(null!=o)r=j(o);else if(null!=a){var s=this.mountChildren(a,e,n);r=s.join("")}}return J[this._tag]&&"\n"===r.charAt(0)?"\n"+r:r},_createInitialChildren:function(e,t,n,r){var i=t.dangerouslySetInnerHTML;if(null!=i)null!=i.__html&&_.queueHTML(r,i.__html);else{var o=L[typeof t.children]?t.children:null,a=null!=o?null:t.children;if(null!=o)""!==o&&_.queueText(r,o);else if(null!=a)for(var s=this.mountChildren(a,e,n),u=0;u0&&r.length<20?n+" (keys: "+r.join(", ")+")":n}function o(e,t){var n=s.get(e);if(!n){return null}return n}var a=n(650),s=(n(628),n(726)),u=(n(677),n(671)),c=(n(626),n(629),{isMounted:function(e){var t=s.get(e);return!!t&&!!t._renderedComponent},enqueueCallback:function(e,t,n){c.validateCallback(t,n);var i=o(e);return i?(i._pendingCallbacks?i._pendingCallbacks.push(t):i._pendingCallbacks=[t],void r(i)):null},enqueueCallbackInternal:function(e,t){e._pendingCallbacks?e._pendingCallbacks.push(t):e._pendingCallbacks=[t],r(e)},enqueueForceUpdate:function(e){var t=o(e,"forceUpdate");t&&(t._pendingForceUpdate=!0,r(t))},enqueueReplaceState:function(e,t){var n=o(e,"replaceState");n&&(n._pendingStateQueue=[t],n._pendingReplaceState=!0,r(n))},enqueueSetState:function(e,t){var n=o(e,"setState");if(n){var i=n._pendingStateQueue||(n._pendingStateQueue=[]);i.push(t),r(n)}},enqueueElementInternal:function(e,t,n){e._pendingElement=t,e._context=n,r(e)},validateCallback:function(e,t){e&&"function"!=typeof e?a("122",t,i(e)):void 0}});e.exports=c},function(e,t,n){"use strict";var r=(n(622),n(630)),i=(n(629),r);e.exports=i},function(e,t,n){"use strict";var r=n(622),i=n(691),o=n(649),a=function(e){this._currentElement=null,this._hostNode=null,this._hostParent=null,this._hostContainerInfo=null,this._domID=0};r(a.prototype,{mountComponent:function(e,t,n,r){var a=n._idCounter++;this._domID=a,this._hostParent=t,this._hostContainerInfo=n;var s=" react-empty: "+this._domID+" ";if(e.useCreateElement){var u=n._ownerDocument,c=u.createComment(s);return o.precacheNode(this,c),i(c)}return e.renderToStaticMarkup?"":""},receiveComponent:function(){},getHostNode:function(){return o.getNodeFromInstance(this)},unmountComponent:function(){o.uncacheNode(this)}}),e.exports=a},function(e,t,n){"use strict";function r(e,t){"_hostNode"in e?void 0:u("33"),"_hostNode"in t?void 0:u("33");for(var n=0,r=e;r;r=r._hostParent)n++;for(var i=0,o=t;o;o=o._hostParent)i++;for(;n-i>0;)e=e._hostParent,n--;for(;i-n>0;)t=t._hostParent,i--;for(var a=n;a--;){if(e===t)return e;e=e._hostParent,t=t._hostParent}return null}function i(e,t){"_hostNode"in e?void 0:u("35"),"_hostNode"in t?void 0:u("35");for(;t;){if(t===e)return!0;t=t._hostParent}return!1}function o(e){return"_hostNode"in e?void 0:u("36"),e._hostParent}function a(e,t,n){for(var r=[];e;)r.push(e),e=e._hostParent;var i;for(i=r.length;i-- >0;)t(r[i],"captured",n);for(i=0;i0;)n(u[c],"captured",o)}var u=n(650);n(626);e.exports={isAncestor:i,getLowestCommonAncestor:r,getParentInstance:o,traverseTwoPhase:a,traverseEnterLeave:s}},function(e,t,n){"use strict";var r=n(650),i=n(622),o=n(690),a=n(691),s=n(649),u=n(696),c=(n(626),n(745),function(e){this._currentElement=e,this._stringText=""+e,this._hostNode=null,this._hostParent=null,this._domID=0,this._mountIndex=0,this._closingComment=null,this._commentNodes=null});i(c.prototype,{mountComponent:function(e,t,n,r){var i=n._idCounter++,o=" react-text: "+i+" ",c=" /react-text ";if(this._domID=i,this._hostParent=t,e.useCreateElement){var l=n._ownerDocument,p=l.createComment(o),f=l.createComment(c),h=a(l.createDocumentFragment());return a.queueChild(h,a(p)),this._stringText&&a.queueChild(h,a(l.createTextNode(this._stringText))),a.queueChild(h,a(f)),s.precacheNode(this,p),this._closingComment=f,h}var d=u(this._stringText);return e.renderToStaticMarkup?d:""+d+""},receiveComponent:function(e,t){if(e!==this._currentElement){this._currentElement=e;var n=""+e;if(n!==this._stringText){this._stringText=n;var r=this.getHostNode();o.replaceDelimitedText(r[0],r[1],n)}}},getHostNode:function(){var e=this._commentNodes;if(e)return e;if(!this._closingComment)for(var t=s.getNodeFromInstance(this),n=t.nextSibling;;){if(null==n?r("67",this._domID):void 0,8===n.nodeType&&" /react-text "===n.nodeValue){this._closingComment=n;break}n=n.nextSibling}return e=[this._hostNode,this._closingComment],this._commentNodes=e,e},unmountComponent:function(){this._closingComment=null,this._commentNodes=null,s.uncacheNode(this)}}),e.exports=c},function(e,t,n){"use strict";
+function r(){this.reinitializeTransaction()}var i=n(622),o=n(671),a=n(678),s=n(630),u={initialize:s,close:function(){f.isBatchingUpdates=!1}},c={initialize:s,close:o.flushBatchedUpdates.bind(o)},l=[c,u];i(r.prototype,a,{getTransactionWrappers:function(){return l}});var p=new r,f={isBatchingUpdates:!1,batchedUpdates:function(e,t,n,r,i,o){var a=f.isBatchingUpdates;return f.isBatchingUpdates=!0,a?e(t,n,r,i,o):p.perform(e,null,t,n,r,i,o)}};e.exports=f},function(e,t,n){"use strict";function r(e){for(;e._hostParent;)e=e._hostParent;var t=p.getNodeFromInstance(e),n=t.parentNode;return p.getClosestInstanceFromNode(n)}function i(e,t){this.topLevelType=e,this.nativeEvent=t,this.ancestors=[]}function o(e){var t=h(e.nativeEvent),n=p.getClosestInstanceFromNode(t),i=n;do e.ancestors.push(i),i=i&&r(i);while(i);for(var o=0;ot.end?(n=t.end,r=t.start):(n=t.start,r=t.end),i.moveToElementText(e),i.moveStart("character",n),i.setEndPoint("EndToStart",i),i.moveEnd("character",r-n),i.select()}function s(e,t){if(window.getSelection){var n=window.getSelection(),r=e[l()].length,i=Math.min(t.start,r),o=void 0===t.end?i:Math.min(t.end,r);if(!n.extend&&i>o){var a=o;o=i,i=a}var s=c(e,i),u=c(e,o);if(s&&u){var p=document.createRange();p.setStart(s.node,s.offset),n.removeAllRanges(),i>o?(n.addRange(p),n.extend(u.node,u.offset)):(p.setEnd(u.node,u.offset),n.addRange(p))}}}var u=n(663),c=n(757),l=n(666),p=u.canUseDOM&&"selection"in document&&!("getSelection"in window),f={getOffsets:p?i:o,setOffsets:p?a:s};e.exports=f},function(e,t){"use strict";function n(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function r(e){for(;e;){if(e.nextSibling)return e.nextSibling;e=e.parentNode}}function i(e,t){for(var i=n(e),o=0,a=0;i;){if(3===i.nodeType){if(a=o+i.textContent.length,o<=t&&a>=t)return{node:i,offset:t-o};o=a}i=n(r(i))}}e.exports=i},function(e,t,n){"use strict";function r(e,t){return!(!e||!t)&&(e===t||!i(e)&&(i(t)?r(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}var i=n(759);e.exports=r},function(e,t,n){"use strict";function r(e){return i(e)&&3==e.nodeType}var i=n(760);e.exports=r},function(e,t){"use strict";function n(e){var t=e?e.ownerDocument||e:document,n=t.defaultView||window;return!(!e||!("function"==typeof n.Node?e instanceof n.Node:"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName))}e.exports=n},function(e,t){(function(t){"use strict";function n(e){if(e=e||t.document,"undefined"==typeof e)return null;try{return e.activeElement||e.body}catch(t){return e.body}}e.exports=n}).call(t,function(){return this}())},function(e,t){"use strict";var n={xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"},r={accentHeight:"accent-height",accumulate:0,additive:0,alignmentBaseline:"alignment-baseline",allowReorder:"allowReorder",alphabetic:0,amplitude:0,arabicForm:"arabic-form",ascent:0,attributeName:"attributeName",attributeType:"attributeType",autoReverse:"autoReverse",azimuth:0,baseFrequency:"baseFrequency",baseProfile:"baseProfile",baselineShift:"baseline-shift",bbox:0,begin:0,bias:0,by:0,calcMode:"calcMode",capHeight:"cap-height",clip:0,clipPath:"clip-path",clipRule:"clip-rule",clipPathUnits:"clipPathUnits",colorInterpolation:"color-interpolation",colorInterpolationFilters:"color-interpolation-filters",colorProfile:"color-profile",colorRendering:"color-rendering",contentScriptType:"contentScriptType",contentStyleType:"contentStyleType",cursor:0,cx:0,cy:0,d:0,decelerate:0,descent:0,diffuseConstant:"diffuseConstant",direction:0,display:0,divisor:0,dominantBaseline:"dominant-baseline",dur:0,dx:0,dy:0,edgeMode:"edgeMode",elevation:0,enableBackground:"enable-background",end:0,exponent:0,externalResourcesRequired:"externalResourcesRequired",fill:0,fillOpacity:"fill-opacity",fillRule:"fill-rule",filter:0,filterRes:"filterRes",filterUnits:"filterUnits",floodColor:"flood-color",floodOpacity:"flood-opacity",focusable:0,fontFamily:"font-family",fontSize:"font-size",fontSizeAdjust:"font-size-adjust",fontStretch:"font-stretch",fontStyle:"font-style",fontVariant:"font-variant",fontWeight:"font-weight",format:0,from:0,fx:0,fy:0,g1:0,g2:0,glyphName:"glyph-name",glyphOrientationHorizontal:"glyph-orientation-horizontal",glyphOrientationVertical:"glyph-orientation-vertical",glyphRef:"glyphRef",gradientTransform:"gradientTransform",gradientUnits:"gradientUnits",hanging:0,horizAdvX:"horiz-adv-x",horizOriginX:"horiz-origin-x",ideographic:0,imageRendering:"image-rendering",in:0,in2:0,intercept:0,k:0,k1:0,k2:0,k3:0,k4:0,kernelMatrix:"kernelMatrix",kernelUnitLength:"kernelUnitLength",kerning:0,keyPoints:"keyPoints",keySplines:"keySplines",keyTimes:"keyTimes",lengthAdjust:"lengthAdjust",letterSpacing:"letter-spacing",lightingColor:"lighting-color",limitingConeAngle:"limitingConeAngle",local:0,markerEnd:"marker-end",markerMid:"marker-mid",markerStart:"marker-start",markerHeight:"markerHeight",markerUnits:"markerUnits",markerWidth:"markerWidth",mask:0,maskContentUnits:"maskContentUnits",maskUnits:"maskUnits",mathematical:0,mode:0,numOctaves:"numOctaves",offset:0,opacity:0,operator:0,order:0,orient:0,orientation:0,origin:0,overflow:0,overlinePosition:"overline-position",overlineThickness:"overline-thickness",paintOrder:"paint-order",panose1:"panose-1",pathLength:"pathLength",patternContentUnits:"patternContentUnits",patternTransform:"patternTransform",patternUnits:"patternUnits",pointerEvents:"pointer-events",points:0,pointsAtX:"pointsAtX",pointsAtY:"pointsAtY",pointsAtZ:"pointsAtZ",preserveAlpha:"preserveAlpha",preserveAspectRatio:"preserveAspectRatio",primitiveUnits:"primitiveUnits",r:0,radius:0,refX:"refX",refY:"refY",renderingIntent:"rendering-intent",repeatCount:"repeatCount",repeatDur:"repeatDur",requiredExtensions:"requiredExtensions",requiredFeatures:"requiredFeatures",restart:0,result:0,rotate:0,rx:0,ry:0,scale:0,seed:0,shapeRendering:"shape-rendering",slope:0,spacing:0,specularConstant:"specularConstant",specularExponent:"specularExponent",speed:0,spreadMethod:"spreadMethod",startOffset:"startOffset",stdDeviation:"stdDeviation",stemh:0,stemv:0,stitchTiles:"stitchTiles",stopColor:"stop-color",stopOpacity:"stop-opacity",strikethroughPosition:"strikethrough-position",strikethroughThickness:"strikethrough-thickness",string:0,stroke:0,strokeDasharray:"stroke-dasharray",strokeDashoffset:"stroke-dashoffset",strokeLinecap:"stroke-linecap",strokeLinejoin:"stroke-linejoin",strokeMiterlimit:"stroke-miterlimit",strokeOpacity:"stroke-opacity",strokeWidth:"stroke-width",surfaceScale:"surfaceScale",systemLanguage:"systemLanguage",tableValues:"tableValues",targetX:"targetX",targetY:"targetY",textAnchor:"text-anchor",textDecoration:"text-decoration",textRendering:"text-rendering",textLength:"textLength",to:0,transform:0,u1:0,u2:0,underlinePosition:"underline-position",underlineThickness:"underline-thickness",unicode:0,unicodeBidi:"unicode-bidi",unicodeRange:"unicode-range",unitsPerEm:"units-per-em",vAlphabetic:"v-alphabetic",vHanging:"v-hanging",vIdeographic:"v-ideographic",vMathematical:"v-mathematical",values:0,vectorEffect:"vector-effect",version:0,vertAdvY:"vert-adv-y",vertOriginX:"vert-origin-x",vertOriginY:"vert-origin-y",viewBox:"viewBox",viewTarget:"viewTarget",visibility:0,widths:0,wordSpacing:"word-spacing",writingMode:"writing-mode",x:0,xHeight:"x-height",x1:0,x2:0,xChannelSelector:"xChannelSelector",xlinkActuate:"xlink:actuate",xlinkArcrole:"xlink:arcrole",xlinkHref:"xlink:href",xlinkRole:"xlink:role",xlinkShow:"xlink:show",xlinkTitle:"xlink:title",xlinkType:"xlink:type",xmlBase:"xml:base",xmlns:0,xmlnsXlink:"xmlns:xlink",xmlLang:"xml:lang",xmlSpace:"xml:space",y:0,y1:0,y2:0,yChannelSelector:"yChannelSelector",z:0,zoomAndPan:"zoomAndPan"},i={Properties:{},DOMAttributeNamespaces:{xlinkActuate:n.xlink,xlinkArcrole:n.xlink,xlinkHref:n.xlink,xlinkRole:n.xlink,xlinkShow:n.xlink,xlinkTitle:n.xlink,xlinkType:n.xlink,xmlBase:n.xml,xmlLang:n.xml,xmlSpace:n.xml},DOMAttributeNames:{}};Object.keys(r).forEach(function(e){i.Properties[e]=0,r[e]&&(i.DOMAttributeNames[e]=r[e])}),e.exports=i},function(e,t,n){"use strict";function r(e){if("selectionStart"in e&&u.hasSelectionCapabilities(e))return{start:e.selectionStart,end:e.selectionEnd};if(window.getSelection){var t=window.getSelection();return{anchorNode:t.anchorNode,anchorOffset:t.anchorOffset,focusNode:t.focusNode,focusOffset:t.focusOffset}}if(document.selection){var n=document.selection.createRange();return{parentElement:n.parentElement(),text:n.text,top:n.boundingTop,left:n.boundingLeft}}}function i(e,t){if(g||null==m||m!==l())return null;var n=r(m);if(!v||!f(v,n)){v=n;var i=c.getPooled(d.select,y,e,t);return i.type="select",i.target=m,o.accumulateTwoPhaseDispatches(i),i}return null}var o=n(656),a=n(663),s=n(649),u=n(755),c=n(668),l=n(761),p=n(681),f=n(731),h=a.canUseDOM&&"documentMode"in document&&document.documentMode<=11,d={select:{phasedRegistrationNames:{bubbled:"onSelect",captured:"onSelectCapture"},dependencies:["topBlur","topContextMenu","topFocus","topKeyDown","topKeyUp","topMouseDown","topMouseUp","topSelectionChange"]}},m=null,y=null,v=null,g=!1,_=!1,b={eventTypes:d,extractEvents:function(e,t,n,r){if(!_)return null;var o=t?s.getNodeFromInstance(t):window;switch(e){case"topFocus":(p(o)||"true"===o.contentEditable)&&(m=o,y=t,v=null);break;case"topBlur":m=null,y=null,v=null;break;case"topMouseDown":g=!0;break;case"topContextMenu":case"topMouseUp":return g=!1,i(n,r);case"topSelectionChange":if(h)break;case"topKeyDown":case"topKeyUp":return i(n,r)}return null},didPutListener:function(e,t,n){"onSelect"===t&&(_=!0)}};e.exports=b},function(e,t,n){"use strict";function r(e){return"."+e._rootNodeID}function i(e){return"button"===e||"input"===e||"select"===e||"textarea"===e}var o=n(650),a=n(751),s=n(656),u=n(649),c=n(765),l=n(766),p=n(668),f=n(767),h=n(768),d=n(684),m=n(771),y=n(772),v=n(773),g=n(685),_=n(774),b=n(630),w=n(769),x=(n(626),{}),k={};["abort","animationEnd","animationIteration","animationStart","blur","canPlay","canPlayThrough","click","contextMenu","copy","cut","doubleClick","drag","dragEnd","dragEnter","dragExit","dragLeave","dragOver","dragStart","drop","durationChange","emptied","encrypted","ended","error","focus","input","invalid","keyDown","keyPress","keyUp","load","loadedData","loadedMetadata","loadStart","mouseDown","mouseMove","mouseOut","mouseOver","mouseUp","paste","pause","play","playing","progress","rateChange","reset","scroll","seeked","seeking","stalled","submit","suspend","timeUpdate","touchCancel","touchEnd","touchMove","touchStart","transitionEnd","volumeChange","waiting","wheel"].forEach(function(e){var t=e[0].toUpperCase()+e.slice(1),n="on"+t,r="top"+t,i={phasedRegistrationNames:{bubbled:n,captured:n+"Capture"},dependencies:[r]};x[e]=i,k[r]=i});var S={},E={eventTypes:x,extractEvents:function(e,t,n,r){var i=k[e];if(!i)return null;var a;switch(e){case"topAbort":case"topCanPlay":case"topCanPlayThrough":case"topDurationChange":case"topEmptied":case"topEncrypted":case"topEnded":case"topError":case"topInput":case"topInvalid":case"topLoad":case"topLoadedData":case"topLoadedMetadata":case"topLoadStart":case"topPause":case"topPlay":case"topPlaying":case"topProgress":case"topRateChange":case"topReset":case"topSeeked":case"topSeeking":case"topStalled":case"topSubmit":case"topSuspend":case"topTimeUpdate":case"topVolumeChange":case"topWaiting":a=p;break;case"topKeyPress":if(0===w(n))return null;case"topKeyDown":case"topKeyUp":a=h;break;case"topBlur":case"topFocus":a=f;break;case"topClick":if(2===n.button)return null;case"topDoubleClick":case"topMouseDown":case"topMouseMove":case"topMouseUp":case"topMouseOut":case"topMouseOver":case"topContextMenu":a=d;break;case"topDrag":case"topDragEnd":case"topDragEnter":case"topDragExit":case"topDragLeave":case"topDragOver":case"topDragStart":case"topDrop":a=m;break;case"topTouchCancel":case"topTouchEnd":case"topTouchMove":case"topTouchStart":a=y;break;case"topAnimationEnd":case"topAnimationIteration":case"topAnimationStart":a=c;break;case"topTransitionEnd":a=v;break;case"topScroll":a=g;break;case"topWheel":a=_;break;case"topCopy":case"topCut":case"topPaste":a=l}a?void 0:o("86",e);var u=a.getPooled(i,t,n,r);return s.accumulateTwoPhaseDispatches(u),u},didPutListener:function(e,t,n){if("onClick"===t&&!i(e._tag)){var o=r(e),s=u.getNodeFromInstance(e);S[o]||(S[o]=a.listen(s,"click",b))}},willDeleteListener:function(e,t){if("onClick"===t&&!i(e._tag)){var n=r(e);S[n].remove(),delete S[n]}}};e.exports=E},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(668),o={animationName:null,elapsedTime:null,pseudoElement:null};i.augmentClass(r,o),e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(668),o={clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}};i.augmentClass(r,o),e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(685),o={relatedTarget:null};i.augmentClass(r,o),e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(685),o=n(769),a=n(770),s=n(687),u={key:a,location:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,repeat:null,locale:null,getModifierState:s,charCode:function(e){return"keypress"===e.type?o(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?o(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}};i.augmentClass(r,u),e.exports=r},function(e,t){"use strict";function n(e){var t,n=e.keyCode;return"charCode"in e?(t=e.charCode,0===t&&13===n&&(t=13)):t=n,t>=32||13===t?t:0}e.exports=n},function(e,t,n){"use strict";function r(e){if(e.key){var t=o[e.key]||e.key;if("Unidentified"!==t)return t}if("keypress"===e.type){var n=i(e);return 13===n?"Enter":String.fromCharCode(n)}return"keydown"===e.type||"keyup"===e.type?a[e.keyCode]||"Unidentified":""}var i=n(769),o={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},a={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"};e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(684),o={dataTransfer:null};i.augmentClass(r,o),e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(685),o=n(687),a={touches:null,targetTouches:null,changedTouches:null,altKey:null,metaKey:null,ctrlKey:null,shiftKey:null,getModifierState:o};i.augmentClass(r,a),e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(668),o={propertyName:null,elapsedTime:null,pseudoElement:null};i.augmentClass(r,o),e.exports=r},function(e,t,n){"use strict";function r(e,t,n,r){return i.call(this,e,t,n,r)}var i=n(684),o={deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:null,deltaMode:null};i.augmentClass(r,o),e.exports=r},function(e,t,n){"use strict";function r(e,t){for(var n=Math.min(e.length,t.length),r=0;r.":"function"==typeof t?" Instead of passing a class like Foo, pass React.createElement(Foo) or .":null!=t&&void 0!==t.props?" This may be caused by unintentionally loading two independent copies of React.":"");var a,s=y.createElement(N,{child:t});if(e){var u=x.get(e);a=u._processChildContext(u._context)}else a=A;var l=f(n);if(l){var p=l._currentElement,d=p.props.child;if(D(d,t)){var m=l._renderedComponent.getPublicInstance(),v=r&&function(){r.call(m)};return z._updateRootComponent(l,s,a,n,v),m}z.unmountComponentAtNode(n)}var g=i(n),_=g&&!!o(g),b=c(n),w=_&&!l&&!b,k=z._renderNewRootComponent(s,n,w,a)._renderedComponent.getPublicInstance();return r&&r.call(k),k},render:function(e,t,n){return z._renderSubtreeIntoContainer(null,e,t,n)},unmountComponentAtNode:function(e){l(e)?void 0:h("40");var t=f(e);if(!t){c(e),1===e.nodeType&&e.hasAttribute(P);return!1}return delete F[t._instance.rootID],C.batchedUpdates(u,t,e,!1),!0},_mountImageIntoNode:function(e,t,n,o,a){if(l(t)?void 0:h("41"),o){var s=i(t);if(k.canReuseMarkup(e,s))return void g.precacheNode(n,s);var u=s.getAttribute(k.CHECKSUM_ATTR_NAME);s.removeAttribute(k.CHECKSUM_ATTR_NAME);var c=s.outerHTML;s.setAttribute(k.CHECKSUM_ATTR_NAME,u);var p=e,f=r(p,c),m=" (client) "+p.substring(f-20,f+20)+"\n (server) "+c.substring(f-20,f+20);t.nodeType===j?h("42",m):void 0}if(t.nodeType===j?h("43"):void 0,a.useCreateElement){for(;t.lastChild;)t.removeChild(t.lastChild);d.insertTreeBefore(t,e,null)}else O(t,e),g.precacheNode(n,t.firstChild)}};e.exports=z},function(e,t,n){"use strict";function r(e,t){var n={_topLevelWrapper:e,_idCounter:1,_ownerDocument:t?t.nodeType===i?t:t.ownerDocument:null,_node:t,_tag:t?t.nodeName.toLowerCase():null,_namespaceURI:t?t.namespaceURI:null};return n}var i=(n(745),9);e.exports=r},function(e,t){"use strict";var n={useCreateElement:!0,useFiber:!1};e.exports=n},function(e,t,n){"use strict";var r=n(779),i=/\/?>/,o=/^<\!\-\-/,a={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(e){var t=r(e);return o.test(e)?e:e.replace(i," "+a.CHECKSUM_ATTR_NAME+'="'+t+'"$&')},canReuseMarkup:function(e,t){var n=t.getAttribute(a.CHECKSUM_ATTR_NAME);n=n&&parseInt(n,10);var i=r(e);return i===n}};e.exports=a},function(e,t){"use strict";function n(e){for(var t=1,n=0,i=0,o=e.length,a=o&-4;i3&&void 0!==arguments[3]?arguments[3]:{},c=Boolean(e),f=e||S,d=void 0;d="function"==typeof t?t:t?(0,v.default)(t):E;var y=n||C,g=r.pure,_=void 0===g||g,b=r.withRef,x=void 0!==b&&b,O=_&&y!==C,D=T++;return function(e){function t(e,t,n){var r=y(e,t,n);return r}var n="Connect("+s(e)+")",r=function(r){function s(e,t){i(this,s);var a=o(this,r.call(this,e,t));a.version=D,a.store=e.store||t.store,(0,k.default)(a.store,'Could not find "store" in either the context or '+('props of "'+n+'". ')+"Either wrap the root component in a , "+('or explicitly pass "store" as a prop to "'+n+'".'));var u=a.store.getState();return a.state={storeState:u},a.clearCache(),a}return a(s,r),s.prototype.shouldComponentUpdate=function(){return!_||this.haveOwnPropsChanged||this.hasStoreStateChanged},s.prototype.computeStateProps=function(e,t){if(!this.finalMapStateToProps)return this.configureFinalMapState(e,t);var n=e.getState(),r=this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(n,t):this.finalMapStateToProps(n);return r},s.prototype.configureFinalMapState=function(e,t){var n=f(e.getState(),t),r="function"==typeof n;return this.finalMapStateToProps=r?n:f,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,r?this.computeStateProps(e,t):n},s.prototype.computeDispatchProps=function(e,t){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(e,t);var n=e.dispatch,r=this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(n,t):this.finalMapDispatchToProps(n);return r},s.prototype.configureFinalMapDispatch=function(e,t){var n=d(e.dispatch,t),r="function"==typeof n;return this.finalMapDispatchToProps=r?n:d,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,r?this.computeDispatchProps(e,t):n},s.prototype.updateStatePropsIfNeeded=function(){var e=this.computeStateProps(this.store,this.props);return(!this.stateProps||!(0,m.default)(e,this.stateProps))&&(this.stateProps=e,!0)},s.prototype.updateDispatchPropsIfNeeded=function(){var e=this.computeDispatchProps(this.store,this.props);return(!this.dispatchProps||!(0,m.default)(e,this.dispatchProps))&&(this.dispatchProps=e,!0)},s.prototype.updateMergedPropsIfNeeded=function(){var e=t(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&O&&(0,m.default)(e,this.mergedProps))&&(this.mergedProps=e,!0)},s.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},s.prototype.trySubscribe=function(){c&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},s.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},s.prototype.componentDidMount=function(){this.trySubscribe()},s.prototype.componentWillReceiveProps=function(e){_&&(0,m.default)(e,this.props)||(this.haveOwnPropsChanged=!0)},s.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},s.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,
+this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},s.prototype.handleChange=function(){if(this.unsubscribe){var e=this.store.getState(),t=this.state.storeState;if(!_||t!==e){if(_&&!this.doStatePropsDependOnOwnProps){var n=u(this.updateStatePropsIfNeeded,this);if(!n)return;n===A&&(this.statePropsPrecalculationError=A.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:e})}}},s.prototype.getWrappedInstance=function(){return(0,k.default)(x,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},s.prototype.render=function(){var t=this.haveOwnPropsChanged,n=this.hasStoreStateChanged,r=this.haveStatePropsBeenPrecalculated,i=this.statePropsPrecalculationError,o=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,i)throw i;var a=!0,s=!0;_&&o&&(a=n||t&&this.doStatePropsDependOnOwnProps,s=t&&this.doDispatchPropsDependOnOwnProps);var u=!1,c=!1;r?u=!0:a&&(u=this.updateStatePropsIfNeeded()),s&&(c=this.updateDispatchPropsIfNeeded());var f=!0;return f=!!(u||c||t)&&this.updateMergedPropsIfNeeded(),!f&&o?o:(x?this.renderedElement=(0,p.createElement)(e,l({},this.mergedProps,{ref:"wrappedInstance"})):this.renderedElement=(0,p.createElement)(e,this.mergedProps),this.renderedElement)},s}(p.Component);return r.displayName=n,r.WrappedComponent=e,r.contextTypes={store:h.default},r.propTypes={store:h.default},(0,w.default)(r,e)}}t.__esModule=!0;var l=Object.assign||function(e){for(var t=1;t1),t}),s(e,c(e),n),u&&(n=i(n,l|p|f));for(var h=t.length;h--;)o(n,t[h]);return n});e.exports=h},function(e,t,n){function r(e,t,n,A,T,O){var D,I=t&k,j=t&S,F=t&E;if(n&&(D=T?n(e,A,T,O):n(e)),void 0!==D)return D;if(!w(e))return e;var B=_(e);if(B){if(D=y(e),!I)return l(e,D)}else{var N=m(e),z=N==M||N==P;if(b(e))return c(e,I);if(N==R||N==C||z&&!T){if(D=j||z?{}:g(e),!I)return j?f(e,u(D,e)):p(e,s(D,e))}else{if(!Z[N])return T?e:{};D=v(e,N,r,I)}}O||(O=new i);var L=O.get(e);if(L)return L;O.set(e,D);var U=F?j?d:h:j?keysIn:x,q=B?void 0:U(e);return o(q||e,function(i,o){q&&(o=i,i=e[o]),a(D,o,r(i,t,n,o,e,O))}),D}var i=n(404),o=n(795),a=n(796),s=n(799),u=n(801),c=n(805),l=n(806),p=n(807),f=n(810),h=n(813),d=n(815),m=n(439),y=n(816),v=n(817),g=n(827),_=n(347),b=n(427),w=n(375),x=n(422),k=1,S=2,E=4,C="[object Arguments]",A="[object Array]",T="[object Boolean]",O="[object Date]",D="[object Error]",M="[object Function]",P="[object GeneratorFunction]",I="[object Map]",j="[object Number]",R="[object Object]",F="[object RegExp]",B="[object Set]",N="[object String]",z="[object Symbol]",L="[object WeakMap]",U="[object ArrayBuffer]",q="[object DataView]",W="[object Float32Array]",K="[object Float64Array]",V="[object Int8Array]",H="[object Int16Array]",J="[object Int32Array]",G="[object Uint8Array]",X="[object Uint8ClampedArray]",Y="[object Uint16Array]",$="[object Uint32Array]",Z={};Z[C]=Z[A]=Z[U]=Z[q]=Z[T]=Z[O]=Z[W]=Z[K]=Z[V]=Z[H]=Z[J]=Z[I]=Z[j]=Z[R]=Z[F]=Z[B]=Z[N]=Z[z]=Z[G]=Z[X]=Z[Y]=Z[$]=!0,Z[D]=Z[M]=Z[L]=!1,e.exports=r},function(e,t){function n(e,t){for(var n=-1,r=null==e?0:e.length;++n0){if(++t>=r)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}var r=800,i=16,o=Date.now;e.exports=n},function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{fn:o}};var i=n(469),o=r(i)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){function t(e){for(var t,n=arguments.length,r=Array(n>1?n-1:0),o=1;o=a&&(t=console)[e].apply(t,r)}var n=e.configs,r={debug:0,info:1,log:2,warn:3,error:4},i=function(e){return r[e]||-1},o=n.logLevel,a=i(o);return t.warn=t.bind(null,"warn"),t.error=t.bind(null,"error"),t.info=t.bind(null,"info"),t.debug=t.bind(null,"debug"),{rootInjects:{log:t}}}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{fn:{AST:a},components:{JumpToPath:u.default}}};var o=n(845),a=i(o),s=n(875),u=r(s)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){function n(e,t,i){if(!e)return i&&i.start_mark?i.start_mark.line:0;if(t.length&&e.tag===v)for(r=0;r=t.column:t.line===e.start_mark.line?t.column>=e.start_mark.column:t.line===e.end_mark.line?t.column<=e.end_mark.column:e.start_mark.linet.line}var o=0;if(!e||[v,g].indexOf(e.tag)===-1)return i;if(e.tag===v)for(o=0;o0&&(a=this.buffer[u-1],e.call(r,a)<0);)if(u--,this.pointer-u>n/2-1){o=" ... ",u+=5;break}for(c="",i=this.pointer;in/2-1){c=" ... ",i-=5;break}return""+new Array(t).join(" ")+o+this.buffer.slice(u,i)+c+"\n"+new Array(t+this.pointer-u+o.length).join(" ")+"^"},t.prototype.toString=function(){var e,t;return e=this.get_snippet(),t=" on line "+(this.line+1)+", column "+(this.column+1),e?t:t+":\n"+e},t}(),this.YAMLError=function(e){function n(e){this.message=e,n.__super__.constructor.call(this),this.stack=this.toString()+"\n"+(new Error).stack.split("\n").slice(1).join("\n")}return t(n,e),n.prototype.toString=function(){return this.message},n}(Error),this.MarkedYAMLError=function(e){function n(e,t,r,i,o){this.context=e,this.context_mark=t,this.problem=r,this.problem_mark=i,this.note=o,n.__super__.constructor.call(this)}return t(n,e),n.prototype.toString=function(){var e;return e=[],null!=this.context&&e.push(this.context),null==this.context_mark||null!=this.problem&&null!=this.problem_mark&&this.context_mark.line===this.problem_mark.line&&this.context_mark.column===this.problem_mark.column||e.push(this.context_mark.toString()),null!=this.problem&&e.push(this.problem),null!=this.problem_mark&&e.push(this.problem_mark.toString()),null!=this.note&&e.push(this.note),e.join("\n")},n}(this.YAMLError)}).call(this)},function(e,t){(function(){var e,t=function(e,t){function r(){this.constructor=e}for(var i in t)n.call(t,i)&&(e[i]=t[i]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e},n={}.hasOwnProperty;e=0,this.Node=function(){function t(t,n,r,i){this.tag=t,this.value=n,this.start_mark=r,this.end_mark=i,this.unique_id="node_"+e++}return t}(),this.ScalarNode=function(e){function n(e,t,r,i,o){this.tag=e,this.value=t,this.start_mark=r,this.end_mark=i,this.style=o,n.__super__.constructor.apply(this,arguments)}return t(n,e),n.prototype.id="scalar",n}(this.Node),this.CollectionNode=function(e){function n(e,t,r,i,o){this.tag=e,this.value=t,this.start_mark=r,this.end_mark=i,this.flow_style=o,n.__super__.constructor.apply(this,arguments)}return t(n,e),n}(this.Node),this.SequenceNode=function(e){function n(){return n.__super__.constructor.apply(this,arguments)}return t(n,e),n.prototype.id="sequence",n}(this.CollectionNode),this.MappingNode=function(e){function n(){return n.__super__.constructor.apply(this,arguments)}return t(n,e),n.prototype.id="mapping",n}(this.CollectionNode)}).call(this)},function(e,t,n){(function(e){(function(){var r,i,o,a=function(e,t){function n(){this.constructor=e}for(var r in t)s.call(t,r)&&(e[r]=t[r]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},s={}.hasOwnProperty,u=[].indexOf||function(e){for(var t=0,n=this.length;t=0)throw new t.ConstructorError(null,null,"found unconstructable recursive node",e.start_mark);if(this.constructing_nodes.push(e.unique_id),n=null,s=null,e.tag in this.yaml_constructors)n=this.yaml_constructors[e.tag];else{for(a in this.yaml_multi_constructors)if(e.tag.indexOf(0===a)){s=e.tag.slice(a.length),n=this.yaml_multi_constructors[a];break}null==n&&(null in this.yaml_multi_constructors?(s=e.tag,n=this.yaml_multi_constructors[null]):null in this.yaml_constructors?n=this.yaml_constructors[null]:e instanceof i.ScalarNode?n=this.construct_scalar:e instanceof i.SequenceNode?n=this.construct_sequence:e instanceof i.MappingNode&&(n=this.construct_mapping))}return r=n.call(this,null!=s?s:e,e),this.constructed_objects[e.unique_id]=r,this.constructing_nodes.pop(),r},e.prototype.construct_scalar=function(e){if(!(e instanceof i.ScalarNode))throw new t.ConstructorError(null,null,"expected a scalar node but found "+e.id,e.start_mark);return e.value},e.prototype.construct_sequence=function(e){var n,r,o,a,s;if(!(e instanceof i.SequenceNode))throw new t.ConstructorError(null,null,"expected a sequence node but found "+e.id,e.start_mark);for(a=e.value,s=[],r=0,o=a.length;r=0&&(l=l.slice(1)),"0"===l)return 0;if(0===l.indexOf("0b"))return c*parseInt(l.slice(2),2);if(0===l.indexOf("0x"))return c*parseInt(l.slice(2),16);if(0===l.indexOf("0o"))return c*parseInt(l.slice(2),8);if("0"===l[0])return c*parseInt(l,8);if(u.call(l,":")>=0){for(r=function(){var e,t,n,r;for(n=l.split(/:/g),r=[],e=0,t=n.length;e=0&&(l=l.slice(1)),".inf"===l)return c*(1/0);if(".nan"===l)return NaN;if(u.call(l,":")>=0){for(r=function(){var e,t,n,r;for(n=l.split(/:/g),r=[],e=0,t=n.length;e=n?e:e.length+1===n?""+t+e:""+new Array(n-e.length+1).join(t)+e},this.to_hex=function(e){return"string"==typeof e&&(e=e.charCodeAt(0)),e.toString(16)}}).call(this)}).call(t,function(){return this}())},function(e,t,n){(function(e,r){function i(e,n){var r={seen:[],stylize:a};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),m(n)?r.showHidden=n:n&&t._extend(r,n),w(r.showHidden)&&(r.showHidden=!1),w(r.depth)&&(r.depth=2),w(r.colors)&&(r.colors=!1),w(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=o),u(r,e,r.depth)}function o(e,t){var n=i.styles[t];return n?"["+i.colors[n][0]+"m"+e+"["+i.colors[n][1]+"m":e}function a(e,t){return e}function s(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}function u(e,n,r){if(e.customInspect&&n&&C(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var i=n.inspect(r,e);return _(i)||(i=u(e,i,r)),i}var o=c(e,n);if(o)return o;var a=Object.keys(n),m=s(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),E(n)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return l(n);if(0===a.length){if(C(n)){var y=n.name?": "+n.name:"";return e.stylize("[Function"+y+"]","special")}if(x(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(S(n))return e.stylize(Date.prototype.toString.call(n),"date");if(E(n))return l(n)}var v="",g=!1,b=["{","}"];if(d(n)&&(g=!0,b=["[","]"]),C(n)){var w=n.name?": "+n.name:"";v=" [Function"+w+"]"}if(x(n)&&(v=" "+RegExp.prototype.toString.call(n)),S(n)&&(v=" "+Date.prototype.toUTCString.call(n)),E(n)&&(v=" "+l(n)),0===a.length&&(!g||0==n.length))return b[0]+v+b[1];if(r<0)return x(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special");e.seen.push(n);var k;return k=g?p(e,n,r,m,a):a.map(function(t){return f(e,n,r,m,t,g)}),e.seen.pop(),h(k,v,b)}function c(e,t){if(w(t))return e.stylize("undefined","undefined");if(_(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}return g(t)?e.stylize(""+t,"number"):m(t)?e.stylize(""+t,"boolean"):y(t)?e.stylize("null","null"):void 0}function l(e){return"["+Error.prototype.toString.call(e)+"]"}function p(e,t,n,r,i){for(var o=[],a=0,s=t.length;a-1&&(s=o?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n"))):s=e.stylize("[Circular]","special")),w(a)){if(o&&i.match(/^\d+$/))return s;a=JSON.stringify(""+i),a.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function h(e,t,n){var r=0,i=e.reduce(function(e,t){return r++,t.indexOf("\n")>=0&&r++,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0);return i>60?n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1]:n[0]+t+" "+e.join(", ")+" "+n[1]}function d(e){return Array.isArray(e)}function m(e){return"boolean"==typeof e}function y(e){return null===e}function v(e){return null==e}function g(e){return"number"==typeof e}function _(e){return"string"==typeof e}function b(e){return"symbol"==typeof e}function w(e){return void 0===e}function x(e){return k(e)&&"[object RegExp]"===T(e)}function k(e){return"object"==typeof e&&null!==e}function S(e){return k(e)&&"[object Date]"===T(e)}function E(e){return k(e)&&("[object Error]"===T(e)||e instanceof Error)}function C(e){return"function"==typeof e}function A(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function T(e){return Object.prototype.toString.call(e)}function O(e){return e<10?"0"+e.toString(10):e.toString(10)}function D(){var e=new Date,t=[O(e.getHours()),O(e.getMinutes()),O(e.getSeconds())].join(":");return[e.getDate(),R[e.getMonth()],t].join(" ")}function M(e,t){return Object.prototype.hasOwnProperty.call(e,t)}var P=/%[sdj%]/g;t.format=function(e){if(!_(e)){for(var t=[],n=0;n=o)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),s=r[n];n2*this.indent?t.width:80,this.best_line_break="\r"===(n=t.line_break)||"\n"===n||"\r\n"===n?t.line_break:"\n",this.tag_prefixes=null,this.prepared_anchor=null,this.prepared_tag=null,this.analysis=null,this.style=null}var r,a,c;return r="\0 \t\r\n
\u2028\u2029",a={"!":"!","tag:yaml.org,2002:":"!!"},c={"\0":"0","":"a","\b":"b","\t":"t","\n":"n","\v":"v","\f":"f","\r":"r","":"e",'"':'"',"\\":"\\","
":"N"," ":"_","\u2028":"L","\u2029":"P"},n.prototype.dispose=function(){return this.states=[],this.state=null},n.prototype.emit=function(e){var t;for(this.events.push(e),t=[];!this.need_more_events();)this.event=this.events.shift(),this.state(),t.push(this.event=null);return t},n.prototype.need_more_events=function(){var e;return 0===this.events.length||(e=this.events[0],e instanceof i.DocumentStartEvent?this.need_events(1):e instanceof i.SequenceStartEvent?this.need_events(2):e instanceof i.MappingStartEvent&&this.need_events(3))},n.prototype.need_events=function(e){var t,n,r,o,a;for(o=0,a=this.events.slice(1),n=0,r=a.length;nthis.best_width)&&this.write_indent(),this.states.push(this.expect_flow_sequence_item),this.expect_node({sequence:!0}))},n.prototype.expect_flow_sequence_item=function(){return this.event instanceof i.SequenceEndEvent?(this.indent=this.indents.pop(),this.flow_level--,this.canonical&&(this.write_indicator(",",!1),this.write_indent()),this.write_indicator("]",!1),this.state=this.states.pop()):(this.write_indicator(",",!1),(this.canonical||this.column>this.best_width)&&this.write_indent(),this.states.push(this.expect_flow_sequence_item),this.expect_node({sequence:!0}))},n.prototype.expect_flow_mapping=function(){return this.write_indicator("{",!0,{whitespace:!0}),this.flow_level++,this.increase_indent({flow:!0}),this.state=this.expect_first_flow_mapping_key},n.prototype.expect_first_flow_mapping_key=function(){return this.event instanceof i.MappingEndEvent?(this.indent=this.indents.pop(),this.flow_level--,this.write_indicator("}",!1),this.state=this.states.pop()):((this.canonical||this.column>this.best_width)&&this.write_indent(),!this.canonical&&this.check_simple_key()?(this.states.push(this.expect_flow_mapping_simple_value),this.expect_node({mapping:!0,simple_key:!0})):(this.write_indicator("?",!0),this.states.push(this.expect_flow_mapping_value),this.expect_node({mapping:!0})))},n.prototype.expect_flow_mapping_key=function(){return this.event instanceof i.MappingEndEvent?(this.indent=this.indents.pop(),this.flow_level--,this.canonical&&(this.write_indicator(",",!1),this.write_indent()),this.write_indicator("}",!1),this.state=this.states.pop()):(this.write_indicator(",",!1),(this.canonical||this.column>this.best_width)&&this.write_indent(),!this.canonical&&this.check_simple_key()?(this.states.push(this.expect_flow_mapping_simple_value),this.expect_node({mapping:!0,simple_key:!0})):(this.write_indicator("?",!0),this.states.push(this.expect_flow_mapping_value),this.expect_node({mapping:!0})))},n.prototype.expect_flow_mapping_simple_value=function(){return this.write_indicator(":",!1),this.states.push(this.expect_flow_mapping_key),this.expect_node({mapping:!0})},n.prototype.expect_flow_mapping_value=function(){return(this.canonical||this.column>this.best_width)&&this.write_indent(),this.write_indicator(":",!0),this.states.push(this.expect_flow_mapping_key),this.expect_node({mapping:!0})},n.prototype.expect_block_sequence=function(){var e;return e=this.mapping_context&&!this.indentation,this.increase_indent({indentless:e}),this.state=this.expect_first_block_sequence_item},n.prototype.expect_first_block_sequence_item=function(){return this.expect_block_sequence_item(!0)},n.prototype.expect_block_sequence_item=function(e){return null==e&&(e=!1),!e&&this.event instanceof i.SequenceEndEvent?(this.indent=this.indents.pop(),this.state=this.states.pop()):(this.write_indent(),this.write_indicator("-",!0,{indentation:!0}),this.states.push(this.expect_block_sequence_item),this.expect_node({sequence:!0}))},n.prototype.expect_block_mapping=function(){return this.increase_indent(),this.state=this.expect_first_block_mapping_key},n.prototype.expect_first_block_mapping_key=function(){return this.expect_block_mapping_key(!0)},n.prototype.expect_block_mapping_key=function(e){return null==e&&(e=!1),!e&&this.event instanceof i.MappingEndEvent?(this.indent=this.indents.pop(),this.state=this.states.pop()):(this.write_indent(),this.check_simple_key()?(this.states.push(this.expect_block_mapping_simple_value),this.expect_node({mapping:!0,simple_key:!0})):(this.write_indicator("?",!0,{indentation:!0}),this.states.push(this.expect_block_mapping_value),this.expect_node({mapping:!0})))},n.prototype.expect_block_mapping_simple_value=function(){return this.write_indicator(":",!1),this.states.push(this.expect_block_mapping_key),this.expect_node({mapping:!0})},n.prototype.expect_block_mapping_value=function(){return this.write_indent(),this.write_indicator(":",!0,{indentation:!0}),this.states.push(this.expect_block_mapping_key),this.expect_node({mapping:!0})},n.prototype.check_empty_document=function(){var e;return this.event instanceof i.DocumentStartEvent&&0!==this.events.length&&(e=this.events[0],e instanceof i.ScalarEvent&&null==e.anchor&&null==e.tag&&e.implicit&&""===e.value)},n.prototype.check_empty_sequence=function(){return this.event instanceof i.SequenceStartEvent&&this.events[0]instanceof i.SequenceEndEvent},n.prototype.check_empty_mapping=function(){return this.event instanceof i.MappingStartEvent&&this.events[0]instanceof i.MappingEndEvent},n.prototype.check_simple_key=function(){var e;return e=0,this.event instanceof i.NodeEvent&&null!=this.event.anchor&&(null==this.prepared_anchor&&(this.prepared_anchor=this.prepare_anchor(this.event.anchor)),e+=this.prepared_anchor.length),null!=this.event.tag&&(this.event instanceof i.ScalarEvent||this.event instanceof i.CollectionStartEvent)&&(null==this.prepared_tag&&(this.prepared_tag=this.prepare_tag(this.event.tag)),e+=this.prepared_tag.length),this.event instanceof i.ScalarEvent&&(null==this.analysis&&(this.analysis=this.analyze_scalar(this.event.value)),e+=this.analysis.scalar.length),e<128&&(this.event instanceof i.AliasEvent||this.event instanceof i.ScalarEvent&&!this.analysis.empty&&!this.analysis.multiline||this.check_empty_sequence()||this.check_empty_mapping())},n.prototype.process_anchor=function(e){return null==this.event.anchor?void(this.prepared_anchor=null):(null==this.prepared_anchor&&(this.prepared_anchor=this.prepare_anchor(this.event.anchor)),this.prepared_anchor&&this.write_indicator(""+e+this.prepared_anchor,!0),this.prepared_anchor=null)},n.prototype.process_tag=function(){var e;if(e=this.event.tag,this.event instanceof i.ScalarEvent){if(null==this.style&&(this.style=this.choose_scalar_style()),(!this.canonical||null==e)&&(""===this.style&&this.event.implicit[0]||""!==this.style&&this.event.implicit[1]))return void(this.prepared_tag=null);this.event.implicit[0]&&null==e&&(e="!",this.prepared_tag=null)}else if((!this.canonical||null==e)&&this.event.implicit)return void(this.prepared_tag=null);return null==e&&this.error("tag is not specified"),null==this.prepared_tag&&(this.prepared_tag=this.prepare_tag(e)),this.write_indicator(this.prepared_tag,!0),this.prepared_tag=null},n.prototype.process_scalar=function(){var e;switch(null==this.analysis&&(this.analysis=this.analyze_scalar(this.event.value)),null==this.style&&(this.style=this.choose_scalar_style()),e=!this.simple_key_context,this.style){case'"':this.write_double_quoted(this.analysis.scalar,e);break;case"'":this.write_single_quoted(this.analysis.scalar,e);break;case">":this.write_folded(this.analysis.scalar);break;case"|":this.write_literal(this.analysis.scalar);break;default:this.write_plain(this.analysis.scalar,e)}return this.analysis=null,this.style=null},n.prototype.choose_scalar_style=function(){var e;return null==this.analysis&&(this.analysis=this.analyze_scalar(this.event.value)),'"'===this.event.style||this.canonical?'"':this.event.style||!this.event.implicit[0]||this.simple_key_context&&(this.analysis.empty||this.analysis.multiline)||!(this.flow_level&&this.analysis.allow_flow_plain||!this.flow_level&&this.analysis.allow_block_plain)?this.event.style&&(e=this.event.style,u.call("|>",e)>=0)&&!this.flow_level&&!this.simple_key_context&&this.analysis.allow_block?this.event.style:this.event.style&&"'"!==this.event.style||!this.analysis.allow_single_quoted||this.simple_key_context&&this.analysis.multiline?'"':"'":""},n.prototype.prepare_version=function(e){var t,n,r;return t=e[0],n=e[1],r=t+"."+n,1===t?r:this.error("unsupported YAML version",r)},n.prototype.prepare_tag_handle=function(e){var t,n,r,i;for(e||this.error("tag handle must not be empty"),"!"===e[0]&&"!"===e.slice(-1)||this.error("tag handle must start and end with '!':",e),i=e.slice(1,-1),n=0,r=i.length;n=0||this.error("invalid character '"+t+"' in the tag handle:",e);return e},n.prototype.prepare_tag_prefix=function(e){var t,n,r,i;for(e||this.error("tag prefix must not be empty"),n=[],i=0,r=+("!"===e[0]);r=0?r++:(i=0||"!"===t&&"!"!==i?r++:(f"},n.prototype.prepare_anchor=function(e){var t,n,r;for(e||this.error("anchor must not be empty"),n=0,r=e.length;n=0||this.error("invalid character '"+t+"' in the anchor:",e);return e},n.prototype.analyze_scalar=function(t){var n,i,o,a,s,c,l,p,f,h,d,m,y,v,g,_,b,w,x,k,S,E,C,A,T,O;for(t||new e(t,!0,!1,!1,!0,!0,!0,!1),c=!1,f=!1,_=!1,C=!1,O=!1,v=!1,y=!1,T=!1,A=!1,l=!1,E=!1,0!==t.indexOf("---")&&0!==t.indexOf("...")||(c=!0,f=!0),b=!0,h=1===t.length||(k=t[1],u.call("\0 \t\r\n
\u2028\u2029",k)>=0),x=!1,w=!1,m=0,m=d=0,g=t.length;d'\"%@`",p)>=0||"-"===p&&h?(f=!0,c=!0):u.call("?:",p)>=0&&(f=!0,h&&(c=!0)):u.call(",?[]{}",p)>=0?f=!0:":"===p?(f=!0,h&&(c=!0)):"#"===p&&b&&(f=!0,c=!0),u.call("\n
\u2028\u2029",p)>=0&&(_=!0),"\n"===p||" "<=p&&p<="~"||("\ufeff"!==p&&("
"===p||" "<=p&&p<=""||""<=p&&p<="�")?(O=!0,this.allow_unicode||(C=!0)):C=!0)," "===p?(0===m&&(v=!0),m===t.length-1&&(T=!0),w&&(l=!0),w=!1,x=!0):u.call("\n
\u2028\u2029",p)>=0?(0===m&&(y=!0),m===t.length-1&&(A=!0),x&&(E=!0),w=!0,x=!1):(w=!1,x=!1),b=u.call(r,p)>=0,h=m+2>=t.length||(S=t[m+2],u.call(r,S)>=0);return a=!0,i=!0,s=!0,o=!0,n=!0,(v||y||T||A)&&(a=i=!1),T&&(n=!1),l&&(a=i=s=!1),(E||C)&&(a=i=s=n=!1),_&&(a=i=!1),f&&(a=!1),c&&(i=!1),new e(t,!1,_,a,i,s,o,n)},n.prototype.write_stream_start=function(){if(this.encoding&&0===this.encoding.indexOf("utf-16"))return this.stream.write("\ufeff",this.encoding)},n.prototype.write_stream_end=function(){return this.flush_stream()},n.prototype.write_indicator=function(e,t,n){var r;return null==n&&(n={}),r=this.whitespace||!t?e:" "+e,this.whitespace=!!n.whitespace,this.indentation&&(this.indentation=!!n.indentation),this.column+=r.length,this.open_ended=!1,this.stream.write(r,this.encoding)},n.prototype.write_indent=function(){var e,t,n;if(t=null!=(n=this.indent)?n:0,(!this.indentation||this.column>t||this.column===t&&!this.whitespace)&&this.write_line_break(),this.columnthis.best_width&&t&&0!==f&&a!==e.length?this.write_indent():(o=e.slice(f,a),this.column+=o.length,this.stream.write(o,this.encoding)),f=a);else if(r){if(null==i||u.call("\n
\u2028\u2029",i)<0){for("\n"===e[f]&&this.write_line_break(),l=e.slice(f,a),s=0,c=l.length;s=0||"'"===i)&&f=0),a++}return this.write_indicator("'",!1)},n.prototype.write_double_quoted=function(e,t){var n,r,i,a;for(null==t&&(t=!0),this.write_indicator('"',!0),a=i=0;i<=e.length;)n=e[i],(null==n||u.call('"\\
\u2028\u2029\ufeff',n)>=0||!(" "<=n&&n<="~"||this.allow_unicode&&(" "<=n&&n<=""||""<=n&&n<="�")))&&(a=i)&&this.column+(i-a)>this.best_width&&(r=e.slice(a,i)+"\\",a"+a,!0),"+"===a.slice(-1)&&(this.open_ended=!0),this.write_line_break(),c=!0,n=!0,h=!1,d=o=0,f=[];o<=e.length;){if(r=e[o],n){if(null==r||u.call("\n
\u2028\u2029",r)<0){for(c||null==r||" "===r||"\n"!==e[d]||this.write_line_break(),c=" "===r,p=e.slice(d,o),s=0,l=p.length;sthis.best_width?this.write_indent():(i=e.slice(d,o),this.column+=i.length,this.stream.write(i,this.encoding)),d=o):(null==r||u.call(" \n
\u2028\u2029",r)>=0)&&(i=e.slice(d,o),this.column+=i.length,this.stream.write(i,this.encoding),null==r&&this.write_line_break(),d=o);null!=r&&(n=u.call("\n
\u2028\u2029",r)>=0,h=" "===r),f.push(o++)}return f},n.prototype.write_literal=function(e){var t,n,r,i,o,a,s,c,l,p,f;for(a=this.determine_block_hints(e),this.write_indicator("|"+a,!0),"+"===a.slice(-1)&&(this.open_ended=!0),this.write_line_break(),n=!0,f=o=0,p=[];o<=e.length;){if(r=e[o],n){if(null==r||u.call("\n
\u2028\u2029",r)<0){for(l=e.slice(f,o),s=0,c=l.length;s=0)&&(i=e.slice(f,o),this.stream.write(i,this.encoding),null==r&&this.write_line_break(),f=o);null!=r&&(n=u.call("\n
\u2028\u2029",r)>=0),p.push(o++)}return p},n.prototype.write_plain=function(e,t){var n,r,i,o,a,s,c,l,p,f,h;if(null==t&&(t=!0),e){for(this.root_context&&(this.open_ended=!0),this.whitespace||(o=" ",this.column+=o.length,this.stream.write(o,this.encoding)),this.whitespace=!1,this.indentation=!1,f=!1,r=!1,h=a=0,p=[];a<=e.length;){if(i=e[a],f)" "!==i&&(h+1===a&&this.column>this.best_width&&t?(this.write_indent(),this.whitespace=!1,this.indentation=!1):(o=e.slice(h,a),this.column+=o.length,
+this.stream.write(o,this.encoding)),h=a);else if(r){if(u.call("\n
\u2028\u2029",i)<0){for("\n"===e[h]&&this.write_line_break(),l=e.slice(h,a),s=0,c=l.length;s=0)&&(o=e.slice(h,a),this.column+=o.length,this.stream.write(o,this.encoding),h=a);null!=i&&(f=" "===i,r=u.call("\n
\u2028\u2029",i)>=0),p.push(a++)}return p}},n.prototype.determine_block_hints=function(e){var t,n,r,i,o;return n="",t=e[0],r=e.length-2,o=e[r++],i=e[r++],u.call(" \n
\u2028\u2029",t)>=0&&(n+=this.best_indent),u.call("\n
\u2028\u2029",i)<0?n+="-":(1===e.length||u.call("\n
\u2028\u2029",o)>=0)&&(n+="+"),n},n.prototype.flush_stream=function(){var e;return"function"==typeof(e=this.stream).flush?e.flush():void 0},n.prototype.error=function(e,n){var r,i;throw n&&(n=null!=(r=null!=n&&null!=(i=n.constructor)?i.name:void 0)?r:o.inspect(n)),new t.EmitterError(""+e+(n?" "+n:""))},n}(),e=function(){function e(e,t,n,r,i,o,a,s){this.scalar=e,this.empty=t,this.multiline=n,this.allow_flow_plain=r,this.allow_block_plain=i,this.allow_single_quoted=o,this.allow_double_quoted=a,this.allow_block=s}return e}()}).call(this)},function(e,t,n){(function(){var e,t,r,i,o=function(e,t){function n(){this.constructor=e}for(var r in t)a.call(t,r)&&(e[r]=t[r]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},a={}.hasOwnProperty;t=n(848),r=n(850),i=n(852),e=n(849).YAMLError,this.SerializerError=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return o(t,e),t}(e),this.Serializer=function(){function e(e){var t;t=null!=e?e:{},this.encoding=t.encoding,this.explicit_start=t.explicit_start,this.explicit_end=t.explicit_end,this.version=t.version,this.tags=t.tags,this.serialized_nodes={},this.anchors={},this.last_anchor_id=0,this.closed=null}return e.prototype.open=function(){if(null===this.closed)return this.emit(new t.StreamStartEvent(this.encoding)),this.closed=!1;throw this.closed?new SerializerError("serializer is closed"):new SerializerError("serializer is already open")},e.prototype.close=function(){if(null===this.closed)throw new SerializerError("serializer is not opened");if(!this.closed)return this.emit(new t.StreamEndEvent),this.closed=!0},e.prototype.serialize=function(e){if(null===this.closed)throw new SerializerError("serializer is not opened");if(this.closed)throw new SerializerError("serializer is closed");return null!=e&&(this.emit(new t.DocumentStartEvent(void 0,void 0,this.explicit_start,this.version,this.tags)),this.anchor_node(e),this.serialize_node(e),this.emit(new t.DocumentEndEvent(void 0,void 0,this.explicit_end))),this.serialized_nodes={},this.anchors={},this.last_anchor_id=0},e.prototype.anchor_node=function(e){var t,n,i,o,a,s,u,c,l,p,f,h,d,m;if(e.unique_id in this.anchors)return null!=(t=this.anchors)[c=e.unique_id]?t[c]:t[c]=this.generate_anchor(e);if(this.anchors[e.unique_id]=null,e instanceof r.SequenceNode){for(l=e.value,h=[],n=0,s=l.length;nn?p.push([l,s]):i[s]=this.yaml_path_resolvers[l][s]);else for(d=this.yaml_path_resolvers,a=0,c=d.length;a=0)return c[e];if(a.call(c,null)>=0)return c[null]}return e===t.ScalarNode?i:e===t.SequenceNode?o:e===t.MappingNode?n:void 0},e}(),this.Resolver=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return i(t,e),t}(this.BaseResolver),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:bool",/^(?:yes|Yes|YES|true|True|TRUE|on|On|ON|no|No|NO|false|False|FALSE|off|Off|OFF)$/,"yYnNtTfFoO"),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:float",/^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)?|\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*|[-+]?\.(?:inf|Inf|INF)|\.(?:nan|NaN|NAN))$/,"-+0123456789."),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:int",/^(?:[-+]?0b[01_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?0o[0-7_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$/,"-+0123456789"),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:merge",/^(?:<<)$/,"<"),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:null",/^(?:~|null|Null|NULL|)$/,["~","n","N",""]),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:timestamp",/^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[\x20\t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\.[0-9]*)?(?:[\x20\t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$/,"0123456789"),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:value",/^(?:=)$/,"="),this.Resolver.add_implicit_resolver("tag:yaml.org,2002:yaml",/^(?:!|&|\*)$/,"!&*")}).call(this)},function(e,t,n){(function(){var e,t,r,i,o,a,s,u=[].slice;s=n(852),i=n(862),a=n(863),r=n(865),e=n(847),o=n(860),t=n(851),this.make_loader=function(n,c,l,p,f,h){var d,m;return null==n&&(n=i.Reader),null==c&&(c=a.Scanner),null==l&&(l=r.Parser),null==p&&(p=e.Composer),null==f&&(f=o.Resolver),null==h&&(h=t.Constructor),m=[n,c,l,p,f,h],d=function(){function e(e){var n,r,i;for(m[0].call(this,e),i=m.slice(1),n=0,r=i.length;n=0||"\r"===t&&"\n"!==this.string[this.index]?(this.line++,this.column=0):this.column++,n.push(e--);return n},n.prototype.get_mark=function(){return new e(this.line,this.column,this.string,this.index)},n.prototype.check_printable=function(){var e,n,i;if(n=r.exec(this.string))throw e=n[0],i=this.string.length-this.index+n.index,new t.ReaderError(i,e.charCodeAt(),"special characters are not allowed")},n}()}).call(this)},function(e,t,n){(function(){var e,r,i,o,a=function(e,t){function n(){this.constructor=e}for(var r in t)s.call(t,r)&&(e[r]=t[r]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},s={}.hasOwnProperty,u=[].slice,c=[].indexOf||function(e){for(var t=0,n=this.length;t"===e&&0===this.flow_level)return this.fetch_folded();if("'"===e)return this.fetch_single();if('"'===e)return this.fetch_double();if(this.check_plain())return this.fetch_plain();throw new t.ScannerError("while scanning for the next token",null,"found character "+e+" that cannot start any token",this.get_mark())},e.prototype.next_possible_simple_key=function(){var e,t,n,r;n=null,r=this.possible_simple_keys;for(t in r)s.call(r,t)&&(e=r[t],(null===n||e.token_numbere;)t=this.get_mark(),this.indent=this.indents.pop(),n.push(this.tokens.push(new i.BlockEndToken(t,t)));return n}},e.prototype.add_indent=function(e){return e>this.indent&&(this.indents.push(this.indent),this.indent=e,!0)},e.prototype.fetch_stream_start=function(){var e;return e=this.get_mark(),this.tokens.push(new i.StreamStartToken(e,e,this.encoding))},e.prototype.fetch_stream_end=function(){var e;return this.unwind_indent(-1),this.remove_possible_simple_key(),this.allow_possible_simple_key=!1,this.possible_simple_keys={},e=this.get_mark(),this.tokens.push(new i.StreamEndToken(e,e)),this.done=!0},e.prototype.fetch_directive=function(){return this.unwind_indent(-1),this.remove_possible_simple_key(),this.allow_simple_key=!1,this.tokens.push(this.scan_directive())},e.prototype.fetch_document_start=function(){return this.fetch_document_indicator(i.DocumentStartToken)},e.prototype.fetch_document_end=function(){return this.fetch_document_indicator(i.DocumentEndToken)},e.prototype.fetch_document_indicator=function(e){var t;return this.unwind_indent(-1),this.remove_possible_simple_key(),this.allow_simple_key=!1,t=this.get_mark(),this.forward(3),this.tokens.push(new e(t,this.get_mark()))},e.prototype.fetch_flow_sequence_start=function(){return this.fetch_flow_collection_start(i.FlowSequenceStartToken)},e.prototype.fetch_flow_mapping_start=function(){return this.fetch_flow_collection_start(i.FlowMappingStartToken)},e.prototype.fetch_flow_collection_start=function(e){var t;return this.save_possible_simple_key(),this.flow_level++,this.allow_simple_key=!0,t=this.get_mark(),this.forward(),this.tokens.push(new e(t,this.get_mark()))},e.prototype.fetch_flow_sequence_end=function(){return this.fetch_flow_collection_end(i.FlowSequenceEndToken)},e.prototype.fetch_flow_mapping_end=function(){return this.fetch_flow_collection_end(i.FlowMappingEndToken)},e.prototype.fetch_flow_collection_end=function(e){var t;return this.remove_possible_simple_key(),this.flow_level--,this.allow_simple_key=!1,t=this.get_mark(),this.forward(),this.tokens.push(new e(t,this.get_mark()))},e.prototype.fetch_flow_entry=function(){var e;return this.allow_simple_key=!0,this.remove_possible_simple_key(),e=this.get_mark(),this.forward(),this.tokens.push(new i.FlowEntryToken(e,this.get_mark()))},e.prototype.fetch_block_entry=function(){var e,n;if(0===this.flow_level){if(!this.allow_simple_key)throw new t.ScannerError(null,null,"sequence entries are not allowed here",this.get_mark());this.add_indent(this.column)&&(e=this.get_mark(),this.tokens.push(new i.BlockSequenceStartToken(e,e)))}return this.allow_simple_key=!0,this.remove_possible_simple_key(),n=this.get_mark(),this.forward(),this.tokens.push(new i.BlockEntryToken(n,this.get_mark()))},e.prototype.fetch_key=function(){var e,n;if(0===this.flow_level){if(!this.allow_simple_key)throw new t.ScannerError(null,null,"mapping keys are not allowed here",this.get_mark());this.add_indent(this.column)&&(e=this.get_mark(),this.tokens.push(new i.BlockMappingStartToken(e,e)))}return this.allow_simple_key=!this.flow_level,this.remove_possible_simple_key(),n=this.get_mark(),this.forward(),this.tokens.push(new i.KeyToken(n,this.get_mark()))},e.prototype.fetch_value=function(){var e,n,r;if(e=this.possible_simple_keys[this.flow_level])delete this.possible_simple_keys[this.flow_level],this.tokens.splice(e.token_number-this.tokens_taken,0,new i.KeyToken(e.mark,e.mark)),0===this.flow_level&&this.add_indent(e.column)&&this.tokens.splice(e.token_number-this.tokens_taken,0,new i.BlockMappingStartToken(e.mark,e.mark)),this.allow_simple_key=!1;else{if(0===this.flow_level){if(!this.allow_simple_key)throw new t.ScannerError(null,null,"mapping values are not allowed here",this.get_mark());this.add_indent(this.column)&&(n=this.get_mark(),this.tokens.push(new i.BlockMappingStartToken(n,n)))}this.allow_simple_key=!this.flow_level,this.remove_possible_simple_key()}return r=this.get_mark(),this.forward(),this.tokens.push(new i.ValueToken(r,this.get_mark()))},e.prototype.fetch_alias=function(){return this.save_possible_simple_key(),this.allow_simple_key=!1,this.tokens.push(this.scan_anchor(i.AliasToken))},e.prototype.fetch_anchor=function(){return this.save_possible_simple_key(),this.allow_simple_key=!1,this.tokens.push(this.scan_anchor(i.AnchorToken))},e.prototype.fetch_tag=function(){return this.save_possible_simple_key(),this.allow_simple_key=!1,this.tokens.push(this.scan_tag())},e.prototype.fetch_literal=function(){return this.fetch_block_scalar("|")},e.prototype.fetch_folded=function(){return this.fetch_block_scalar(">")},e.prototype.fetch_block_scalar=function(e){return this.allow_simple_key=!0,this.remove_possible_simple_key(),this.tokens.push(this.scan_block_scalar(e))},e.prototype.fetch_single=function(){return this.fetch_flow_scalar("'")},e.prototype.fetch_double=function(){return this.fetch_flow_scalar('"')},e.prototype.fetch_flow_scalar=function(e){return this.save_possible_simple_key(),this.allow_simple_key=!1,this.tokens.push(this.scan_flow_scalar(e))},e.prototype.fetch_plain=function(){return this.save_possible_simple_key(),this.allow_simple_key=!1,this.tokens.push(this.scan_plain())},e.prototype.check_directive=function(){return 0===this.column},e.prototype.check_document_start=function(){var e;return 0===this.column&&"---"===this.prefix(3)&&(e=this.peek(3),c.call(n+l+"\0",e)>=0)},e.prototype.check_document_end=function(){var e;return 0===this.column&&"..."===this.prefix(3)&&(e=this.peek(3),c.call(n+l+"\0",e)>=0)},e.prototype.check_block_entry=function(){var e;return e=this.peek(1),c.call(n+l+"\0",e)>=0},e.prototype.check_key=function(){var e;return 0!==this.flow_level||(e=this.peek(1),c.call(n+l+"\0",e)>=0)},e.prototype.check_value=function(){var e;return 0!==this.flow_level||(e=this.peek(1),c.call(n+l+"\0",e)>=0)},e.prototype.check_plain=function(){var e,t;return e=this.peek(),c.call(n+l+"\0-?:,[]{}#&*!|>'\"%@`",e)<0||(t=this.peek(1),c.call(n+l+"\0",t)<0&&("-"===e||0===this.flow_level&&c.call("?:",e)>=0))},e.prototype.scan_to_next_token=function(){var e,t,r;for(0===this.index&&"\ufeff"===this.peek()&&this.forward(),e=!1,r=[];!e;){for(;" "===this.peek();)this.forward();if("#"===this.peek())for(;t=this.peek(),c.call(n+"\0",t)<0;)this.forward();this.scan_line_break()?0===this.flow_level?r.push(this.allow_simple_key=!0):r.push(void 0):r.push(e=!0)}return r},e.prototype.scan_directive=function(){var e,t,r,o,a;if(o=this.get_mark(),this.forward(),t=this.scan_directive_name(o),a=null,"YAML"===t)a=this.scan_yaml_directive_value(o),e=this.get_mark();else if("TAG"===t)a=this.scan_tag_directive_value(o),e=this.get_mark();else for(e=this.get_mark();r=this.peek(),c.call(n+"\0",r)<0;)this.forward();return this.scan_directive_ignored_line(o),new i.DirectiveToken(t,a,o,e)},e.prototype.scan_directive_name=function(e){var r,i,o;for(i=0,r=this.peek(i);"0"<=r&&r<="9"||"A"<=r&&r<="Z"||"a"<=r&&r<="z"||c.call("-_",r)>=0;)i++,r=this.peek(i);if(0===i)throw new t.ScannerError("while scanning a directive",e,"expected alphanumeric or numeric character but found "+r,this.get_mark());if(o=this.prefix(i),this.forward(i),r=this.peek(),c.call(n+"\0 ",r)<0)throw new t.ScannerError("while scanning a directive",e,"expected alphanumeric or numeric character but found "+r,this.get_mark());return o},e.prototype.scan_yaml_directive_value=function(e){for(var r,i,o;" "===this.peek();)this.forward();if(r=this.scan_yaml_directive_number(e),"."!==this.peek())throw new t.ScannerError("while scanning a directive",e,"expected a digit or '.' but found "+this.peek(),this.get_mark());if(this.forward(),i=this.scan_yaml_directive_number(e),o=this.peek(),c.call(n+"\0 ",o)<0)throw new t.ScannerError("while scanning a directive",e,"expected a digit or ' ' but found "+this.peek(),this.get_mark());return[r,i]},e.prototype.scan_yaml_directive_number=function(e){var n,r,i,o;if(n=this.peek(),!("0"<=n&&n<="9"))throw new t.ScannerError("while scanning a directive",e,"expected a digit but found "+n,this.get_mark());for(r=0;"0"<=(i=this.peek(r))&&i<="9";)r++;return o=parseInt(this.prefix(r)),this.forward(r),o},e.prototype.scan_tag_directive_value=function(e){for(var t,n;" "===this.peek();)this.forward();for(t=this.scan_tag_directive_handle(e);" "===this.peek();)this.forward();return n=this.scan_tag_directive_prefix(e),[t,n]},e.prototype.scan_tag_directive_handle=function(e){var n,r;if(r=this.scan_tag_handle("directive",e),n=this.peek()," "!==n)throw new t.ScannerError("while scanning a directive",e,"expected ' ' but found "+n,this.get_mark());return r},e.prototype.scan_tag_directive_prefix=function(e){var r,i;if(i=this.scan_tag_uri("directive",e),r=this.peek(),c.call(n+"\0 ",r)<0)throw new t.ScannerError("while scanning a directive",e,"expected ' ' but found "+r,this.get_mark());return i},e.prototype.scan_directive_ignored_line=function(e){for(var r,i;" "===this.peek();)this.forward();if("#"===this.peek())for(;i=this.peek(),c.call(n+"\0",i)<0;)this.forward();if(r=this.peek(),c.call(n+"\0",r)<0)throw new t.ScannerError("while scanning a directive",e,"expected a comment or a line break but found "+r,this.get_mark());return this.scan_line_break()},e.prototype.scan_anchor=function(e){var r,i,o,a,s,u;for(s=this.get_mark(),i=this.peek(),a="*"===i?"alias":"anchor",this.forward(),o=0,r=this.peek(o);"0"<=r&&r<="9"||"A"<=r&&r<="Z"||"a"<=r&&r<="z"||c.call("-_",r)>=0;)o++,r=this.peek(o);if(0===o)throw new t.ScannerError("while scanning an "+a,s,"expected alphabetic or numeric character but found '"+r+"'",this.get_mark());if(u=this.prefix(o),this.forward(o),r=this.peek(),c.call(n+l+"\0?:,]}%@`",r)<0)throw new t.ScannerError("while scanning an "+a,s,"expected alphabetic or numeric character but found '"+r+"'",this.get_mark());return new e(u,s,this.get_mark())},e.prototype.scan_tag=function(){var e,r,o,a,s,u;if(a=this.get_mark(),e=this.peek(1),"<"===e){if(r=null,this.forward(2),s=this.scan_tag_uri("tag",a),">"!==this.peek())throw new t.ScannerError("while parsing a tag",a,"expected '>' but found "+this.peek(),this.get_mark());this.forward()}else if(c.call(n+l+"\0",e)>=0)r=null,s="!",this.forward();else{for(o=1,u=!1;c.call(n+"\0 ",e)<0;){if("!"===e){u=!0;break}o++,e=this.peek(o)}u?r=this.scan_tag_handle("tag",a):(r="!",this.forward()),s=this.scan_tag_uri("tag",a)}if(e=this.peek(),c.call(n+"\0 ",e)<0)throw new t.ScannerError("while scanning a tag",a,"expected ' ' but found "+e,this.get_mark());return new i.TagToken([r,s],a,this.get_mark())},e.prototype.scan_block_scalar=function(e){var t,r,a,s,u,l,p,f,h,d,m,y,v,g,_,b,w,x,k,S;for(u=">"===e,a=[],S=this.get_mark(),this.forward(),v=this.scan_block_scalar_indicators(S),r=v[0],l=v[1],this.scan_block_scalar_ignored_line(S),y=this.indent+1,y<1&&(y=1),null==l?(g=this.scan_block_scalar_indentation(),t=g[0],m=g[1],s=g[2],p=Math.max(y,m)):(p=y+l-1,_=this.scan_block_scalar_breaks(p),t=_[0],s=_[1]),d="";this.column===p&&"\0"!==this.peek();){for(a=a.concat(t),b=this.peek(),f=c.call(" \t",b)<0,h=0;w=this.peek(h),c.call(n+"\0",w)<0;)h++;if(a.push(this.prefix(h)),
+this.forward(h),d=this.scan_line_break(),x=this.scan_block_scalar_breaks(p),t=x[0],s=x[1],this.column!==p||"\0"===this.peek())break;u&&"\n"===d&&f&&(k=this.peek(),c.call(" \t",k)<0)?o.is_empty(t)&&a.push(" "):a.push(d)}return r!==!1&&a.push(d),r===!0&&(a=a.concat(t)),new i.ScalarToken(a.join(""),!1,S,s,e)},e.prototype.scan_block_scalar_indicators=function(e){var r,i,o;if(i=null,o=null,r=this.peek(),c.call("+-",r)>=0){if(i="+"===r,this.forward(),r=this.peek(),c.call(a,r)>=0){if(o=parseInt(r),0===o)throw new t.ScannerError("while scanning a block scalar",e,"expected indentation indicator in the range 1-9 but found 0",this.get_mark());this.forward()}}else if(c.call(a,r)>=0){if(o=parseInt(r),0===o)throw new t.ScannerError("while scanning a block scalar",e,"expected indentation indicator in the range 1-9 but found 0",this.get_mark());this.forward(),r=this.peek(),c.call("+-",r)>=0&&(i="+"===r,this.forward())}if(r=this.peek(),c.call(n+"\0 ",r)<0)throw new t.ScannerError("while scanning a block scalar",e,"expected chomping or indentation indicators, but found "+r,this.get_mark());return[i,o]},e.prototype.scan_block_scalar_ignored_line=function(e){for(var r,i;" "===this.peek();)this.forward();if("#"===this.peek())for(;i=this.peek(),c.call(n+"\0",i)<0;)this.forward();if(r=this.peek(),c.call(n+"\0",r)<0)throw new t.ScannerError("while scanning a block scalar",e,"expected a comment or a line break but found "+r,this.get_mark());return this.scan_line_break()},e.prototype.scan_block_scalar_indentation=function(){var e,t,r,i;for(e=[],r=0,t=this.get_mark();i=this.peek(),c.call(n+" ",i)>=0;)" "!==this.peek()?(e.push(this.scan_line_break()),t=this.get_mark()):(this.forward(),this.column>r&&(r=this.column));return[e,r,t]},e.prototype.scan_block_scalar_breaks=function(e){var t,r,i;for(t=[],r=this.get_mark();this.column=0;)for(t.push(this.scan_line_break()),r=this.get_mark();this.column=0)o.push(i),this.forward();else{if(!e||"\\"!==i)return o;if(this.forward(),i=this.peek(),i in f)o.push(f[i]),this.forward();else if(i in p){for(d=p[i],this.forward(),h=u=0,y=d;0<=y?uy;h=0<=y?++u:--u)if(v=this.peek(h),c.call(a+"ABCDEFabcdef",v)<0)throw new t.ScannerError("while scanning a double-quoted scalar",r,"expected escape sequence of "+d+" hexadecimal numbers, but found "+this.peek(h),this.get_mark());s=parseInt(this.prefix(d),16),o.push(String.fromCharCode(s)),this.forward(d)}else{if(!(c.call(n,i)>=0))throw new t.ScannerError("while scanning a double-quoted scalar",r,"found unknown escape character "+i,this.get_mark());this.scan_line_break(),o=o.concat(this.scan_flow_scalar_breaks(e,r))}}else o.push("'"),this.forward(2)}},e.prototype.scan_flow_scalar_spaces=function(e,r){var i,o,a,s,u,p,f;for(a=[],s=0;p=this.peek(s),c.call(l,p)>=0;)s++;if(f=this.prefix(s),this.forward(s),o=this.peek(),"\0"===o)throw new t.ScannerError("while scanning a quoted scalar",r,"found unexpected end of stream",this.get_mark());return c.call(n,o)>=0?(u=this.scan_line_break(),i=this.scan_flow_scalar_breaks(e,r),"\n"!==u?a.push(u):0===i.length&&a.push(" "),a=a.concat(i)):a.push(f),a},e.prototype.scan_flow_scalar_breaks=function(e,r){var i,o,a,s,u;for(i=[];;){if(o=this.prefix(3),"---"===o||"..."===o&&(a=this.peek(3),c.call(n+l+"\0",a)>=0))throw new t.ScannerError("while scanning a quoted scalar",r,"found unexpected document separator",this.get_mark());for(;s=this.peek(),c.call(l,s)>=0;)this.forward();if(u=this.peek(),!(c.call(n,u)>=0))return i;i.push(this.scan_line_break())}},e.prototype.scan_plain=function(){var e,r,o,a,s,u,p,f,h;for(r=[],h=o=this.get_mark(),a=this.indent+1,f=[];;){if(s=0,"#"===this.peek())break;for(;;){if(e=this.peek(s),c.call(n+l+"\0",e)>=0||0===this.flow_level&&":"===e&&(u=this.peek(s+1),c.call(n+l+"\0",u)>=0)||0!==this.flow_level&&c.call(",:?[]{}",e)>=0)break;s++}if(0!==this.flow_level&&":"===e&&(p=this.peek(s+1),c.call(n+l+"\0,[]{}",p)<0))throw this.forward(s),new t.ScannerError("while scanning a plain scalar",h,"found unexpected ':'",this.get_mark(),"Please check http://pyyaml.org/wiki/YAMLColonInFlowContext");if(0===s)break;if(this.allow_simple_key=!1,r=r.concat(f),r.push(this.prefix(s)),this.forward(s),o=this.get_mark(),f=this.scan_plain_spaces(a,h),null==f||0===f.length||"#"===this.peek()||0===this.flow_level&&this.column=0;)a++;if(m=this.prefix(a),this.forward(a),i=this.peek(),c.call(n,i)>=0){if(s=this.scan_line_break(),this.allow_simple_key=!0,u=this.prefix(3),"---"===u||"..."===u&&(f=this.peek(3),c.call(n+l+"\0",f)>=0))return;for(r=[];d=this.peek(),c.call(n+" ",d)>=0;)if(" "===this.peek())this.forward();else if(r.push(this.scan_line_break()),u=this.prefix(3),"---"===u||"..."===u&&(h=this.peek(3),c.call(n+l+"\0",h)>=0))return;"\n"!==s?o.push(s):0===r.length&&o.push(" "),o=o.concat(r)}else m&&o.push(m);return o},e.prototype.scan_tag_handle=function(e,n){var r,i,o;if(r=this.peek(),"!"!==r)throw new t.ScannerError("while scanning a "+e,n,"expected '!' but found "+r,this.get_mark());if(i=1,r=this.peek(i)," "!==r){for(;"0"<=r&&r<="9"||"A"<=r&&r<="Z"||"a"<=r&&r<="z"||c.call("-_",r)>=0;)i++,r=this.peek(i);if("!"!==r)throw this.forward(i),new t.ScannerError("while scanning a "+e,n,"expected '!' but found "+r,this.get_mark());i++}return o=this.prefix(i),this.forward(i),o},e.prototype.scan_tag_uri=function(e,n){var r,i,o;for(i=[],o=0,r=this.peek(o);"0"<=r&&r<="9"||"A"<=r&&r<="Z"||"a"<=r&&r<="z"||c.call("-;/?:@&=+$,_.!~*'()[]%",r)>=0;)"%"===r?(i.push(this.prefix(o)),this.forward(o),o=0,i.push(this.scan_uri_escapes(e,n))):o++,r=this.peek(o);if(0!==o&&(i.push(this.prefix(o)),this.forward(o),o=0),0===i.length)throw new t.ScannerError("while parsing a "+e,n,"expected URI but found "+r,this.get_mark());return i.join("")},e.prototype.scan_uri_escapes=function(e,n){var r,i,o,a;for(r=[],a=this.get_mark();"%"===this.peek();){for(this.forward(),o=i=0;i<=2;o=++i)throw new t.ScannerError("while scanning a "+e,n,"expected URI escape sequence of 2 hexadecimal numbers but found "+this.peek(o),this.get_mark());r.push(String.fromCharCode(parseInt(this.prefix(2),16))),this.forward(2)}return r.join("")},e.prototype.scan_line_break=function(){var e;return e=this.peek(),c.call("\r\n
",e)>=0?("\r\n"===this.prefix(2)?this.forward(2):this.forward(),"\n"):c.call("\u2028\u2029",e)>=0?(this.forward(),e):""},e}()}).call(this)},function(e,t){(function(){var e=function(e,n){function r(){this.constructor=e}for(var i in n)t.call(n,i)&&(e[i]=n[i]);return r.prototype=n.prototype,e.prototype=new r,e.__super__=n.prototype,e},t={}.hasOwnProperty;this.Token=function(){function e(e,t){this.start_mark=e,this.end_mark=t}return e}(),this.DirectiveToken=function(t){function n(e,t,n,r){this.name=e,this.value=t,this.start_mark=n,this.end_mark=r}return e(n,t),n.prototype.id="",n}(this.Token),this.DocumentStartToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="",n}(this.Token),this.DocumentEndToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="",n}(this.Token),this.StreamStartToken=function(t){function n(e,t,n){this.start_mark=e,this.end_mark=t,this.encoding=n}return e(n,t),n.prototype.id="",n}(this.Token),this.StreamEndToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="",n}(this.Token),this.BlockSequenceStartToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="",n}(this.Token),this.BlockMappingStartToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="",n}(this.Token),this.BlockEndToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="",n}(this.Token),this.FlowSequenceStartToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="[",n}(this.Token),this.FlowMappingStartToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="{",n}(this.Token),this.FlowSequenceEndToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="]",n}(this.Token),this.FlowMappingEndToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="}",n}(this.Token),this.KeyToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="?",n}(this.Token),this.ValueToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id=":",n}(this.Token),this.BlockEntryToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id="-",n}(this.Token),this.FlowEntryToken=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return e(n,t),n.prototype.id=",",n}(this.Token),this.AliasToken=function(t){function n(e,t,n){this.value=e,this.start_mark=t,this.end_mark=n}return e(n,t),n.prototype.id="",n}(this.Token),this.AnchorToken=function(t){function n(e,t,n){this.value=e,this.start_mark=t,this.end_mark=n}return e(n,t),n.prototype.id="",n}(this.Token),this.TagToken=function(t){function n(e,t,n){this.value=e,this.start_mark=t,this.end_mark=n}return e(n,t),n.prototype.id="",n}(this.Token),this.ScalarToken=function(t){function n(e,t,n,r,i){this.value=e,this.plain=t,this.start_mark=n,this.end_mark=r,this.style=i}return e(n,t),n.prototype.id="",n}(this.Token)}).call(this)},function(e,t,n){(function(){var e,r,i,o=function(e,t){function n(){this.constructor=e}for(var r in t)a.call(t,r)&&(e[r]=t[r]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},a={}.hasOwnProperty,s=[].slice;r=n(848),e=n(849).MarkedYAMLError,i=n(864),this.ParserError=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return o(t,e),t}(e),this.Parser=function(){function e(){this.current_event=null,this.yaml_version=null,this.tag_handles={},this.states=[],this.marks=[],this.state="parse_stream_start"}var n;return n={"!":"!","!!":"tag:yaml.org,2002:"},e.prototype.dispose=function(){return this.states=[],this.state=null},e.prototype.check_event=function(){var e,t,n,r;if(t=1<=arguments.length?s.call(arguments,0):[],null===this.current_event&&null!=this.state&&(this.current_event=this[this.state]()),null!==this.current_event){if(0===t.length)return!0;for(n=0,r=t.length;n', but found "+this.peek_token().id,this.peek_token().start_mark);u=this.get_token(),e=u.end_mark,n=new r.DocumentStartEvent(a,e,!0,c,s),this.states.push("parse_document_end"),this.state="parse_document_content"}return n},e.prototype.parse_document_end=function(){var e,t,n,o,a;return a=this.peek_token(),o=e=a.start_mark,n=!1,this.check_token(i.DocumentEndToken)&&(a=this.get_token(),e=a.end_mark,n=!0),t=new r.DocumentEndEvent(o,e,n),this.state="parse_document_start",t},e.prototype.parse_document_content=function(){var e;return this.check_token(i.DirectiveToken,i.DocumentStartToken,i.DocumentEndToken,i.StreamEndToken)?(e=this.process_empty_scalar(this.peek_token().start_mark),this.state=this.states.pop(),e):this.parse_block_node()},e.prototype.process_directives=function(){var e,r,o,s,u,c,l,p,f,h;for(this.yaml_version=null,this.tag_handles={};this.check_token(i.DirectiveToken);)if(f=this.get_token(),"YAML"===f.name){if(null!==this.yaml_version)throw new t.ParserError(null,null,"found duplicate YAML directive",f.start_mark);if(u=f.value,r=u[0],o=u[1],1!==r)throw new t.ParserError(null,null,"found incompatible YAML document (version 1.* is required)",f.start_mark);this.yaml_version=f.value}else if("TAG"===f.name){if(c=f.value,e=c[0],s=c[1],e in this.tag_handles)throw new t.ParserError(null,null,"duplicate tag handle "+e,f.start_mark);this.tag_handles[e]=s}p=null,l=this.tag_handles;for(e in l)a.call(l,e)&&(s=l[e],null==p&&(p={}),p[e]=s);h=[this.yaml_version,p];for(e in n)a.call(n,e)&&(s=n[e],s in this.tag_handles||(this.tag_handles[e]=s));return h},e.prototype.parse_block_node=function(){return this.parse_node(!0)},e.prototype.parse_flow_node=function(){return this.parse_node()},e.prototype.parse_block_node_or_indentless_sequence=function(){return this.parse_node(!0,!0)},e.prototype.parse_node=function(e,n){var o,a,s,u,c,l,p,f,h,d,m;if(null==e&&(e=!1),null==n&&(n=!1),this.check_token(i.AliasToken))m=this.get_token(),s=new r.AliasEvent(m.value,m.start_mark,m.end_mark),this.state=this.states.pop();else{if(o=null,h=null,p=a=d=null,this.check_token(i.AnchorToken)?(m=this.get_token(),p=m.start_mark,a=m.end_mark,o=m.value,this.check_token(i.TagToken)&&(m=this.get_token(),d=m.start_mark,a=m.end_mark,h=m.value)):this.check_token(i.TagToken)&&(m=this.get_token(),p=d=m.start_mark,a=m.end_mark,h=m.value,this.check_token(i.AnchorToken)&&(m=this.get_token(),a=m.end_mark,o=m.value)),null!==h)if(u=h[0],f=h[1],null!==u){if(!(u in this.tag_handles))throw new t.ParserError("while parsing a node",p,"found undefined tag handle "+u,d);h=this.tag_handles[u]+f}else h=f;if(null===p&&(p=a=this.peek_token().start_mark),s=null,c=null===h||"!"===h,n&&this.check_token(i.BlockEntryToken))a=this.peek_token().end_mark,s=new r.SequenceStartEvent(o,h,c,p,a),this.state="parse_indentless_sequence_entry";else if(this.check_token(i.ScalarToken))m=this.get_token(),a=m.end_mark,c=m.plain&&null===h||"!"===h?[!0,!1]:null===h?[!1,!0]:[!1,!1],s=new r.ScalarEvent(o,h,c,m.value,p,a,m.style),this.state=this.states.pop();else if(this.check_token(i.FlowSequenceStartToken))a=this.peek_token().end_mark,s=new r.SequenceStartEvent(o,h,c,p,a,!0),this.state="parse_flow_sequence_first_entry";else if(this.check_token(i.FlowMappingStartToken))a=this.peek_token().end_mark,s=new r.MappingStartEvent(o,h,c,p,a,!0),this.state="parse_flow_mapping_first_key";else if(e&&this.check_token(i.BlockSequenceStartToken))a=this.peek_token().end_mark,s=new r.SequenceStartEvent(o,h,c,p,a,!1),this.state="parse_block_sequence_first_entry";else if(e&&this.check_token(i.BlockMappingStartToken))a=this.peek_token().end_mark,s=new r.MappingStartEvent(o,h,c,p,a,!1),this.state="parse_block_mapping_first_key";else{if(null===o&&null===h)throw l=e?"block":"flow",m=this.peek_token(),new t.ParserError("while parsing a "+l+" node",p,"expected the node content, but found "+m.id,m.start_mark);s=new r.ScalarEvent(o,h,[c,!1],"",p,a),this.state=this.states.pop()}}return s},e.prototype.parse_block_sequence_first_entry=function(){var e;return e=this.get_token(),this.marks.push(e.start_mark),this.parse_block_sequence_entry()},e.prototype.parse_block_sequence_entry=function(){var e,n;if(this.check_token(i.BlockEntryToken))return n=this.get_token(),this.check_token(i.BlockEntryToken,i.BlockEndToken)?(this.state="parse_block_sequence_entry",this.process_empty_scalar(n.end_mark)):(this.states.push("parse_block_sequence_entry"),this.parse_block_node());if(!this.check_token(i.BlockEndToken))throw n=this.peek_token(),new t.ParserError("while parsing a block collection",this.marks.slice(-1)[0],"expected , but found "+n.id,n.start_mark);return n=this.get_token(),e=new r.SequenceEndEvent(n.start_mark,n.end_mark),this.state=this.states.pop(),this.marks.pop(),e},e.prototype.parse_indentless_sequence_entry=function(){var e,t;return this.check_token(i.BlockEntryToken)?(t=this.get_token(),this.check_token(i.BlockEntryToken,i.KeyToken,i.ValueToken,i.BlockEndToken)?(this.state="parse_indentless_sequence_entry",this.process_empty_scalar(t.end_mark)):(this.states.push("parse_indentless_sequence_entry"),this.parse_block_node())):(t=this.peek_token(),e=new r.SequenceEndEvent(t.start_mark,t.start_mark),this.state=this.states.pop(),e)},e.prototype.parse_block_mapping_first_key=function(){var e;return e=this.get_token(),this.marks.push(e.start_mark),this.parse_block_mapping_key()},e.prototype.parse_block_mapping_key=function(){var e,n;if(this.check_token(i.KeyToken))return n=this.get_token(),this.check_token(i.KeyToken,i.ValueToken,i.BlockEndToken)?(this.state="parse_block_mapping_value",this.process_empty_scalar(n.end_mark)):(this.states.push("parse_block_mapping_value"),this.parse_block_node_or_indentless_sequence());if(!this.check_token(i.BlockEndToken))throw n=this.peek_token(),new t.ParserError("while parsing a block mapping",this.marks.slice(-1)[0],"expected , but found "+n.id,n.start_mark);return n=this.get_token(),e=new r.MappingEndEvent(n.start_mark,n.end_mark),this.state=this.states.pop(),this.marks.pop(),e},e.prototype.parse_block_mapping_value=function(){var e;return this.check_token(i.ValueToken)?(e=this.get_token(),this.check_token(i.KeyToken,i.ValueToken,i.BlockEndToken)?(this.state="parse_block_mapping_key",this.process_empty_scalar(e.end_mark)):(this.states.push("parse_block_mapping_key"),this.parse_block_node_or_indentless_sequence())):(this.state="parse_block_mapping_key",e=this.peek_token(),this.process_empty_scalar(e.start_mark))},e.prototype.parse_flow_sequence_first_entry=function(){var e;return e=this.get_token(),this.marks.push(e.start_mark),this.parse_flow_sequence_entry(!0)},e.prototype.parse_flow_sequence_entry=function(e){var n,o;if(null==e&&(e=!1),!this.check_token(i.FlowSequenceEndToken)){if(!e){if(!this.check_token(i.FlowEntryToken))throw o=this.peek_token(),new t.ParserError("while parsing a flow sequence",this.marks.slice(-1)[0],"expected ',' or ']', but got "+o.id,o.start_mark);this.get_token()}if(this.check_token(i.KeyToken))return o=this.peek_token(),n=new r.MappingStartEvent(null,null,!0,o.start_mark,o.end_mark,!0),this.state="parse_flow_sequence_entry_mapping_key",n;if(!this.check_token(i.FlowSequenceEndToken))return this.states.push("parse_flow_sequence_entry"),this.parse_flow_node()}return o=this.get_token(),n=new r.SequenceEndEvent(o.start_mark,o.end_mark),this.state=this.states.pop(),this.marks.pop(),n},e.prototype.parse_flow_sequence_entry_mapping_key=function(){var e;return e=this.get_token(),this.check_token(i.ValueToken,i.FlowEntryToken,i.FlowSequenceEndToken)?(this.state="parse_flow_sequence_entry_mapping_value",this.process_empty_scalar(e.end_mark)):(this.states.push("parse_flow_sequence_entry_mapping_value"),this.parse_flow_node())},e.prototype.parse_flow_sequence_entry_mapping_value=function(){var e;return this.check_token(i.ValueToken)?(e=this.get_token(),this.check_token(i.FlowEntryToken,i.FlowSequenceEndToken)?(this.state="parse_flow_sequence_entry_mapping_end",this.process_empty_scalar(e.end_mark)):(this.states.push("parse_flow_sequence_entry_mapping_end"),this.parse_flow_node())):(this.state="parse_flow_sequence_entry_mapping_end",e=this.peek_token(),this.process_empty_scalar(e.start_mark))},e.prototype.parse_flow_sequence_entry_mapping_end=function(){var e;return this.state="parse_flow_sequence_entry",e=this.peek_token(),new r.MappingEndEvent(e.start_mark,e.start_mark)},e.prototype.parse_flow_mapping_first_key=function(){var e;return e=this.get_token(),this.marks.push(e.start_mark),this.parse_flow_mapping_key(!0)},e.prototype.parse_flow_mapping_key=function(e){var n,o;if(null==e&&(e=!1),!this.check_token(i.FlowMappingEndToken)){if(!e){if(!this.check_token(i.FlowEntryToken))throw o=this.peek_token(),new t.ParserError("while parsing a flow mapping",this.marks.slice(-1)[0],"expected ',' or '}', but got "+o.id,o.start_mark);this.get_token()}if(this.check_token(i.KeyToken))return o=this.get_token(),this.check_token(i.ValueToken,i.FlowEntryToken,i.FlowMappingEndToken)?(this.state="parse_flow_mapping_value",this.process_empty_scalar(o.end_mark)):(this.states.push("parse_flow_mapping_value"),this.parse_flow_node());if(!this.check_token(i.FlowMappingEndToken))return this.states.push("parse_flow_mapping_empty_value"),this.parse_flow_node()}return o=this.get_token(),n=new r.MappingEndEvent(o.start_mark,o.end_mark),this.state=this.states.pop(),this.marks.pop(),n},e.prototype.parse_flow_mapping_value=function(){var e;return this.check_token(i.ValueToken)?(e=this.get_token(),this.check_token(i.FlowEntryToken,i.FlowMappingEndToken)?(this.state="parse_flow_mapping_key",this.process_empty_scalar(e.end_mark)):(this.states.push("parse_flow_mapping_key"),this.parse_flow_node())):(this.state="parse_flow_mapping_key",e=this.peek_token(),this.process_empty_scalar(e.start_mark))},e.prototype.parse_flow_mapping_empty_value=function(){return this.state="parse_flow_mapping_key",this.process_empty_scalar(this.peek_token().start_mark)},e.prototype.process_empty_scalar=function(e){return new r.ScalarEvent(null,null,[!0,!1],"",e,e)},e}()}).call(this)},function(e,t,n){function r(e){return n(i(e))}function i(e){return o[e]||function(){throw new Error("Cannot find module '"+e+"'.")}()}var o={"./composer":847,"./composer.js":847,"./constructor":851,"./constructor.js":851,"./dumper":856,"./dumper.js":856,"./emitter":857,"./emitter.js":857,"./errors":849,"./errors.js":849,"./events":848,"./events.js":848,"./loader":861,"./loader.js":861,"./nodes":850,"./nodes.js":850,"./parser":865,"./parser.js":865,"./reader":862,"./reader.js":862,"./representer":859,"./representer.js":859,"./resolver":860,"./resolver.js":860,"./scanner":863,"./scanner.js":863,"./serializer":858,"./serializer.js":858,"./tokens":864,"./tokens.js":864,"./util":852,"./util.js":852,"./yaml":846,"./yaml.js":846};r.keys=function(){return Object.keys(o)},r.resolve=i,e.exports=r,r.id=866},function(e,t){},function(e,t,n){var r=n(869),i=n(870),o=r(i);e.exports=o},function(e,t,n){function r(e){return function(t,n,r){var s=Object(t);if(!o(t)){var u=i(n,3);t=a(t),n=function(e){return u(s[e],e,s)}}var c=e(t,n,r);return c>-1?s[u?t[c]:c]:void 0}}var i=n(401),o=n(438),a=n(422);e.exports=r},function(e,t,n){function r(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var u=null==n?0:a(n);return u<0&&(u=s(r+u,0)),i(e,o(t,3),u)}var i=n(871),o=n(401),a=n(872),s=Math.max;e.exports=r},function(e,t){function n(e,t,n,r){for(var i=e.length,o=n+(r?1:-1);r?o--:++o2&&void 0!==arguments[2]?arguments[2]:"";return e.operationId?e.operationId:o(t,n)}function o(e,t){return w(t)+"-"+e}function a(e){var t=/^([^-]*)-(.*)$/.exec(e),n=(0,g.default)(t,3),r=n[1],i=n[2];return[i,r]}function s(e,t){return e&&e.paths?u(e,function(e){var n=e.pathName,r=e.method,i=e.operation;if(!i||"object"!==("undefined"==typeof i?"undefined":(0,y.default)(i)))return!1;var o=i.operationId;if(o&&o===t)return!0;var s=a(t),u=(0,g.default)(s,2),c=u[0],l=u[1];return c===n&&w(l)===w(r)}):null}function u(e,t){return c(e,t,!0)}function c(e,t,n){if(!e||"object"!==("undefined"==typeof e?"undefined":(0,y.default)(e))||!e.paths||"object"!==(0,y.default)(e.paths))return null;var r=e.paths;for(var i in r)for(var o in r[i])if("PARAMETERS"!==o.toUpperCase()){var a=r[i][o];if(a&&"object"===("undefined"==typeof a?"undefined":(0,y.default)(a))){var s={spec:e,pathName:i,method:o.toUpperCase(),operation:a},u=t(s);if(n&&u)return s}}}function l(e){var t=e.spec,n=t.paths,r={};if(!n)return e;for(var o in n){var a=n[o];if((0,b.default)(a)){var s=a.parameters;for(var u in a){var c=a[u];if((0,b.default)(c)){var l=i(c,o,u);if(l&&(r[l]?r[l].push(c):r[l]=[c],(0,d.default)(r).forEach(function(e){r[e].length>1&&r[e].forEach(function(t,n){t.operationId=e+"_"+n})})),"parameters"!==u){var p=[],h={};for(var m in t)"produces"!==m&&"consumes"!==m&&"security"!==m||(h[m]=t[m],p.push(h));if(s&&(h.parameters=s,p.push(h)),p.length){var y=!0,v=!1,g=void 0;try{for(var _,w=(0,f.default)(p);!(y=(_=w.next()).done);y=!0){var x=_.value;for(var k in x)if(c[k]){if("parameters"===k){var S=!0,E=!1,C=void 0;try{for(var A,T=function(){var e=A.value,t=c[k].some(function(t){return t.name===e.name});t||c[k].push(e)},O=(0,f.default)(x[k]);!(S=(A=O.next()).done);S=!0)T()}catch(e){E=!0,C=e}finally{try{!S&&O.return&&O.return()}finally{if(E)throw C}}}}else c[k]=x[k]}}catch(e){v=!0,g=e}finally{try{!y&&w.return&&w.return()}finally{if(v)throw g}}}}}}}}return e}Object.defineProperty(t,"__esModule",{value:!0});var p=n(9),f=r(p),h=n(0),d=r(h),m=n(2),y=r(m),v=n(14),g=r(v);t.opId=i,t.idFromPathMethod=o,t.pathMethodFromId=a,t.getOperationRaw=s,t.findOperation=u,t.eachOperation=c,t.normalizeSwagger=l;var _=n(17),b=r(_),w=function(e){return String.prototype.toLowerCase.call(e)}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};"object"===("undefined"==typeof e?"undefined":(0,g.default)(e))&&(t=e,e=t.url),t.headers=t.headers||{},C.mergeInQueryOrForm(t),t.requestInterceptor&&(t=t.requestInterceptor(t)||t);var n=t.headers["content-type"]||t.headers["Content-Type"];return/multipart\/form-data/i.test(n)&&(delete t.headers["content-type"],delete t.headers["Content-Type"]),(0,b.default)(t.url,t).then(function(n){var r=C.serializeRes(n,e,t).then(function(e){return t.responseInterceptor&&(e=t.responseInterceptor(e)||e),e});if(!n.ok){var i=new Error(n.statusText);return i.statusCode=i.status=n.status,r.then(function(e){throw i.response=e,i},function(e){throw i.responseError=e,i})}return r})}function o(e){return/json/.test(e)||/xml/.test(e)||/yaml/.test(e)||/text/.test(e)}function a(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.loadSpec,i=void 0!==r&&r,a={ok:e.ok,url:e.url||t,status:e.status,statusText:e.statusText,headers:s(e.headers)},u=i||o(a.headers["content-type"]),c=u?e.text:e.blob||e.buffer;return c.call(e).then(function(e){if(a.text=e,a.data=e,u)try{var t=S.default.safeLoad(e);a.body=t,a.obj=t}catch(e){a.parseError=e}return a})}function s(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t={};return"function"==typeof e.forEach?(e.forEach(function(e,n){void 0!==t[n]?(t[n]=Array.isArray(t[n])?t[n]:[t[n]],t[n].push(e)):t[n]=e}),t):t}function u(e){return"undefined"!=typeof File?e instanceof File:null!==e&&"object"===("undefined"==typeof e?"undefined":(0,g.default)(e))&&"function"==typeof e.pipe}function c(e){var t=e.value,n=e.collectionFormat,r=e.allowEmptyValue,i={csv:",",ssv:"%20",tsv:"%09",pipes:"|"};return"undefined"==typeof t&&r?"":u(t)?t:t&&!Array.isArray(t)?encodeURIComponent(t):Array.isArray(t)&&!n?t.map(encodeURIComponent).join(","):"multi"===n?t.map(encodeURIComponent):t.map(encodeURIComponent).join(i[n])}function l(e){var t=(0,y.default)(e).reduce(function(t,n){var r=function(e){return e&&"object"===("undefined"==typeof e?"undefined":(0,g.default)(e))},i=e[n],o=encodeURIComponent(n),a=r(i)&&!Array.isArray(i);return t[o]=c(a?i:{value:i}),t},{});return x.default.stringify(t,{encode:!1,
+indices:!1})||""}function p(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,r=void 0===t?"":t,i=e.query,o=e.form,a=function(){for(var e=arguments.length,t=Array(e),n=0;n0){var i=t(e,n[n.length-1],n);i&&(r=r.concat(i))}if(Array.isArray(e)){var o=e.map(function(e,r){return v(e,t,n.concat(r))});o&&(r=r.concat(o))}else if(S(e)){var a=(0,z.default)(e).map(function(r){return v(e[r],t,n.concat(r))});a&&(r=r.concat(a))}return r=x(r)}function g(e,t){if(!Array.isArray(t))return!1;for(var n=0,r=t.length;n1&&void 0!==arguments[1]?arguments[1]:{};if("string"==typeof e?n.url=e:n=e,!(this instanceof i))return new i(n);(0,c.default)(this,n);var r=this.resolve().then(function(){return t.disableInterfaces||(0,c.default)(t,i.makeApisTagOperation(t)),t});return r.client=this,r}var o=n(1),a=r(o),s=n(36),u=(r(s),n(6)),c=r(u),l=n(4),p=r(l),f=n(21),h=r(f),d=n(7),m=r(d),y=n(20),v=n(19);i.http=p.default,i.makeHttp=l.makeHttp.bind(null,i.http),i.resolve=h.default,i.execute=v.execute,i.serializeRes=l.serializeRes,i.serializeHeaders=l.serializeHeaders,i.clearCache=f.clearCache,i.parameterBuilders=v.PARAMETER_BUILDERS,i.makeApisTagOperation=y.makeApisTagOperation,i.buildRequest=v.buildRequest,e.exports=i,i.prototype={http:p.default,execute:function(e){return this.applyDefaults(),i.execute((0,a.default)({spec:this.spec,http:this.http.bind(this),securities:{authorized:this.authorizations}},e))},resolve:function(){var e=this;return i.resolve({spec:this.spec,url:this.url,allowMetaPatches:this.allowMetaPatches}).then(function(t){return e.originalSpec=e.spec,e.spec=t.spec,e.errors=t.errors,e})}},i.prototype.applyDefaults=function(){var e=this.spec,t=this.url;if(t&&t.startsWith("http")){var n=m.default.parse(t);e.host||(e.host=n.host),e.schemes||(e.schemes=[n.protocol.replace(":","")]),e.basePath||(e.basePath="/")}}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=e.http,n=e.fetch,r=e.spec,i=e.operationId,o=e.pathName,a=e.method,s=e.parameters,u=e.securities,c=(0,b.default)(e,["http","fetch","spec","operationId","pathName","method","parameters","securities"]);t=t||n||M.default,o&&a&&(i=(0,P.idFromPathMethod)(o,a));var l=j.buildRequest((0,g.default)({spec:r,operationId:i,parameters:s,securities:u},c));return l.body&&(0,E.default)(l.body)&&(l.body=(0,y.default)(l.body)),t(l)}function o(e){var t=e.spec,n=e.operationId,r=e.parameters,i=e.securities,o=e.requestContentType,a=e.responseContentType,s=e.parameterBuilders,u=e.scheme,c=e.requestInterceptor,l=e.responseInterceptor,h=e.contextUrl;s=s||R;var d={url:p({spec:t,scheme:u,contextUrl:h}),credentials:"same-origin",headers:{}};if(c&&(d.requestInterceptor=c),l&&(d.responseInterceptor=l),!n)return d;var m=(0,P.getOperationRaw)(t,n),y=m.operation,v=void 0===y?{}:y,g=m.method,_=m.pathName;return d.url+=_,d.method=(""+g).toUpperCase(),r=r||{},a&&(d.headers.accept=a),I(v.parameters).concat(I(t.paths[_].parameters)).forEach(function(e){var n=s[e.in],i=void 0;if("body"===e.in&&e.schema&&e.schema.properties&&(i=r),i=e&&e.name&&r[e.name],"undefined"!=typeof e.default&&"undefined"==typeof i&&(i=e.default),"undefined"==typeof i&&e.required&&!e.allowEmptyValue)throw new Error("Required parameter "+e.name+" is not provided");n&&n({req:d,parameter:e,value:i,operation:v,spec:t})}),d=f({request:d,securities:i,operation:v,spec:t}),(0,D.mergeInQueryOrForm)(d),(d.body||d.form)&&(o?d.headers["content-type"]=o:Array.isArray(v.consumes)?d.headers["content-type"]=v.consumes[0]:Array.isArray(t.consumes)?d.headers["content-type"]=t.consumes[0]:v.parameters.filter(function(e){return"file"===e.type}).length?d.headers["content-type"]="multipart/form-data":v.parameters.filter(function(e){return"formData"===e.in}).length&&(d.headers["content-type"]="application/x-www-form-urlencoded")),d}function a(e){var t=e.req,n=e.value;t.body=n}function s(e){var t=e.req,n=e.value,r=e.parameter;t.form=t.form||{},(n||r.allowEmptyValue)&&(t.form[r.name]={value:n,allowEmptyValue:r.allowEmptyValue,collectionFormat:r.collectionFormat})}function u(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{},"undefined"!=typeof r&&(t.headers[n.name]=r)}function c(e){var t=e.req,n=e.value,r=e.parameter;t.url=t.url.replace("{"+r.name+"}",encodeURIComponent(n))}function l(e){var t=e.req,n=e.value,r=e.parameter;if(t.query=t.query||{},n)t.query[r.name]={collectionFormat:r.collectionFormat,value:n};else if(r.allowEmptyValue){var i=r.name;t.query[i]=t.query[i]||{},t.query[i].allowEmptyValue=!0}}function p(e){var t=e.spec,n=e.scheme,r=e.contextUrl,i=void 0===r?"":r,o=O.default.parse(i),a=Array.isArray(t.schemes)?t.schemes[0]:null,s=n||a||F(o.protocol)||"http",u=t.host||o.host||"",c=t.basePath||"";if(s&&u){var l=s+"://"+(u+c);return"/"===l[l.length-1]?l.slice(0,-1):l}return""}function f(e){var t=e.request,n=e.securities,r=void 0===n?{}:n,i=e.operation,o=void 0===i?{}:i,a=e.spec,s=(0,x.default)({},t),u=r.authorized,c=void 0===u?{}:u,l=r.specSecurity,p=void 0===l?{}:l,f=o.security||p,h=c&&!!(0,d.default)(c).length,m=a.securityDefinitions;return s.headers=s.headers||{},s.query=s.query||{},(0,d.default)(r).length&&h&&f&&(!Array.isArray(o.security)||o.security.length)?(f.forEach(function(e,t){for(var n in e){var r=c[n];if(r){var i=r.token,o=r.value||r,a=m[n],u=a.type,l=i&&i.access_token,p=i&&i.token_type;if(r)if("apiKey"===u){var f="query"===a.in?"query":"headers";s[f]=s[f]||{},s[f][a.name]=o}else"basic"===u?o.header?s.headers.authorization=o.header:(o.base64=(0,A.default)(o.username+":"+o.password),s.headers.authorization="Basic "+o.base64):"oauth2"===u&&(s.headers.authorization=(p||"Bearer")+" "+l)}}}),s):t}Object.defineProperty(t,"__esModule",{value:!0}),t.PARAMETER_BUILDERS=t.self=void 0;var h=n(0),d=r(h),m=n(10),y=r(m),v=n(1),g=r(v),_=n(29),b=r(_);t.execute=i,t.buildRequest=o,t.bodyBuilder=a,t.formDataBuilder=s,t.headerBuilder=u,t.pathBuilder=c,t.queryBuilder=l,t.baseUrl=p,t.applySecurities=f;var w=n(6),x=r(w),k=n(37),S=(r(k),n(17)),E=r(S),C=n(31),A=r(C),T=n(7),O=r(T),D=n(4),M=r(D),P=n(3),I=function(e){return Array.isArray(e)?e:[]},j=t.self={buildRequest:o},R=t.PARAMETER_BUILDERS={body:a,header:u,query:l,path:c,formData:s},F=function(e){return e?e.replace(/\W/g,""):null}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return function(t){var n=t.pathName,r=t.method;return function(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.execute((0,c.default)({spec:e.spec},(0,p.default)(e,"requestInterceptor","responseInterceptor"),{pathName:n,method:r,parameters:t},i))}}}function o(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=m.makeExecute(e),n=m.mapTagOperations({spec:e.spec,cb:t}),r={};for(var i in n){r[i]={operations:{}};for(var o in n[i])r[i].operations[o]={execute:n[i][o]}}return{apis:r}}function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=m.makeExecute(e);return{apis:m.mapTagOperations({spec:e.spec,cb:t})}}function s(e){var t=e.spec,n=e.cb,r=void 0===n?h:n,i=e.defaultTag,o=void 0===i?"default":i,a={},s={};return(0,f.eachOperation)(t,function(e){var n=e.pathName,i=e.method,u=e.operation,c=u.tags?d(u.tags):[o];c.forEach(function(e){if("string"==typeof e){var o=s[e]=s[e]||{},c=(0,f.opId)(u,n,i),l=r({spec:t,pathName:n,method:i,operation:u});"undefined"!=typeof o[c]?(a[c]=(a[c]||0)+1,o[c+"_"+a[c]]=l):o[c]=l}})}),s}Object.defineProperty(t,"__esModule",{value:!0}),t.self=void 0;var u=n(1),c=r(u);t.makeExecute=i,t.makeApisTagOperationsOperationExecute=o,t.makeApisTagOperation=a,t.mapTagOperations=s;var l=n(38),p=r(l),f=n(3),h=function(){return null},d=function(e){return Array.isArray(e)?e:[e]},m=t.self={mapTagOperations:s,makeExecute:i}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){return function(t){return e({url:t,loadSpec:!0,headers:{Accept:"application/json"}}).then(function(e){return e.body})}}function o(){c.plugins.refs.clearCache()}function a(e){function t(e){s&&(c.plugins.refs.docCache[s]=e),c.plugins.refs.fetchJSON=i(n);var t=[c.plugins.refs];return"strict"!==f&&t.push(c.plugins.allOf),(0,l.default)({spec:e,context:{baseDoc:s},plugins:t,allowMetaPatches:d}).then(p.normalizeSwagger)}var n=e.http,r=e.fetch,o=e.spec,a=e.url,s=e.baseDoc,f=e.mode,h=e.allowMetaPatches,d=void 0===h||h;return s=s||a,n=r||n||u.default,o?t(o):i(n)(s).then(t)}Object.defineProperty(t,"__esModule",{value:!0}),t.makeFetchJSON=i,t.clearCache=o,t.default=a;var s=n(4),u=r(s),c=n(22),l=r(c),p=n(3)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){return new P(e).dispatch()}Object.defineProperty(t,"__esModule",{value:!0}),t.plugins=t.SpecMap=void 0;var o=n(10),a=r(o),s=n(11),u=r(s),c=n(15),l=r(c),p=n(0),f=r(p),h=n(9),d=r(h),m=n(27),y=r(m),v=n(5),g=r(v),_=n(12),b=r(_),w=n(13),x=r(w);t.default=i;var k=n(8),S=r(k),E=n(26),C=r(E),A=n(23),T=r(A),O=n(24),D=r(O),M=100,P=function(){function e(t){(0,b.default)(this,e),(0,g.default)(this,{spec:"",debugLevel:"info",plugins:[],pluginHistory:{},errors:[],mutations:[],promisedPatches:[],state:{},patches:[],context:{},contextTree:new D.default,showDebug:!1,allPatches:[],pluginProp:"specMap",libMethods:(0,g.default)((0,y.default)(this),S.default),allowMetaPatches:!1},t),this.get=this._get.bind(this),this.getContext=this._getContext.bind(this),this.hasRun=this._hasRun.bind(this),this.wrappedPlugins=this.plugins.map(this.wrapPlugin.bind(this)).filter(S.default.isFunction),this.patches.push(S.default.add([],this.spec)),this.patches.push(S.default.context([],this.context)),this.updatePatches(this.patches)}return(0,x.default)(e,[{key:"debug",value:function(e){if(this.debugLevel===e){for(var t,n=arguments.length,r=Array(n>1?n-1:0),i=1;i1?n-1:0),i=1;i0})}},{key:"nextPromisedPatch",value:function(){if(this.promisedPatches.length>0)return u.default.race(this.promisedPatches.map(function(e){return e.value}))}},{key:"getPluginHistory",value:function(e){var t=this.getPluginName(e);return this.pluginHistory[t]||[]}},{key:"getPluginRunCount",value:function(e){return this.getPluginHistory(e).length}},{key:"getPluginHistoryTip",value:function(e){var t=this.getPluginHistory(e),n=t&&t[t.length-1];return n||{}}},{key:"getPluginMutationIndex",value:function(e){var t=this.getPluginHistoryTip(e).mutationIndex;return"number"!=typeof t?-1:t}},{key:"getPluginName",value:function(e){return e.pluginName}},{key:"updatePluginHistory",value:function(e,t){var n=this.getPluginName(e),r=this.pluginHistory[n]=this.pluginHistory[n]||[];r.push(t)}},{key:"updatePatches",value:function(e,t){var n=this;S.default.normalizeArray(e).forEach(function(e){if(e instanceof Error)return void n.errors.push(e);try{if(!S.default.isObject(e))return void n.debug("updatePatches","Got a non-object patch",e);if(n.showDebug&&n.allPatches.push(e),S.default.isPromise(e.value))return n.promisedPatches.push(e),void n.promisedPatchThen(e);if(S.default.isContextPatch(e))return void n.setContext(e.path,e.value);if(S.default.isMutation(e))return void n.updateMutations(e)}catch(e){n.errors.push(e)}})}},{key:"updateMutations",value:function(e){S.default.applyPatch(this.state,e,{allowMetaPatches:this.allowMetaPatches})&&this.mutations.push(e)}},{key:"removePromisedPatch",value:function(e){var t=this.promisedPatches.indexOf(e);return t<0?void this.debug("Tried to remove a promisedPatch that isn't there!"):void this.promisedPatches.splice(t,1)}},{key:"promisedPatchThen",value:function(e){var t=this,n=e.value=e.value.then(function(n){var r=(0,g.default)({},e,{value:n});t.removePromisedPatch(e),t.updatePatches(r)}).catch(function(n){t.removePromisedPatch(e),t.updatePatches(n)});return n}},{key:"getMutations",value:function(e,t){return e=e||0,"number"!=typeof t&&(t=this.mutations.length),this.mutations.slice(e,t)}},{key:"getCurrentMutations",value:function(){return this.getMutationsForPlugin(this.getCurrentPlugin())}},{key:"getMutationsForPlugin",value:function(e){var t=this.getPluginMutationIndex(e);return this.getMutations(t+1)}},{key:"getCurrentPlugin",value:function(){return this.currentPlugin}},{key:"getPatchesOfType",value:function(e,t){return e.filter(t)}},{key:"getLib",value:function(){return this.libMethods}},{key:"_get",value:function(e){return S.default.getIn(this.state,e)}},{key:"_getContext",value:function(e){return this.contextTree.get(e)}},{key:"setContext",value:function(e,t){return this.contextTree.set(e,t)}},{key:"_hasRun",value:function(e){var t=this.getPluginRunCount(this.getCurrentPlugin());return t>(e||0)}},{key:"_clone",value:function(e){return JSON.parse((0,a.default)(e))}},{key:"dispatch",value:function(){function e(){r.currentPlugin=i;var e=r.getCurrentMutations(),n=r.mutations.length-1;try{if(i.isGenerator){var o=!0,a=!1,s=void 0;try{for(var u,c=(0,d.default)(i(e,r.getLib()));!(o=(u=c.next()).done);o=!0){var l=u.value;t(l)}}catch(e){a=!0,s=e}finally{try{!o&&c.return&&c.return()}finally{if(a)throw s}}}else{var p=i(e,r.getLib());t(p)}}catch(e){t([(0,g.default)((0,y.default)(e),{plugin:i})])}finally{r.updatePluginHistory(i,{mutationIndex:n})}return r.dispatch()}function t(e){e&&(e=S.default.fullyNormalizeArray(e),r.updatePatches(e,i))}var n=this,r=this,i=this.nextPlugin();if(!i){var o=this.nextPromisedPatch();if(o)return o.then(function(){return n.dispatch()}).catch(function(){return n.dispatch()});var a={spec:this.state,errors:this.errors};return this.showDebug&&(a.patches=this.allPatches),u.default.resolve(a)}if(r.pluginCount=r.pluginCount||{},r.pluginCount[i]=(r.pluginCount[i]||0)+1,r.pluginCount[i]>M)return u.default.resolve({spec:r.state,errors:r.errors.concat(new Error("We've reached a hard limit of "+M+" plugin runs"))});if(i!==this.currentPlugin&&this.promisedPatches.length){var s=this.promisedPatches.map(function(e){return e.value});return u.default.all(s.map(function(e){return e.then(Function,Function)})).then(function(){return n.dispatch()})}return e()}}]),e}(),I={refs:C.default,allOf:T.default};t.SpecMap=P,t.plugins=I},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={key:"allOf",plugin:function(e,t,n,r,i){if(!i.meta||!i.meta.$$ref){if(!Array.isArray(e)){var o=new TypeError("allOf must be an array");return o.fullPath=n,o}var a=n.slice(0,-1),s=!1;return[r.replace(a,{})].concat(e.map(function(e,t){if(!r.isObject(e)){if(s)return null;s=!0;var i=new TypeError("Elements in allOf must be objects");return i.fullPath=n,i}return r.mergeDeep(a,e)}))}}}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){return o({children:{}},e,t)}function o(e,t,n){return e.value=t||{},e.protoValue=n?(0,c.default)({},n.protoValue,e.value):e.value,(0,s.default)(e.children).forEach(function(t){var n=e.children[t];e.children[t]=o(n,n.value,e)}),e}Object.defineProperty(t,"__esModule",{value:!0});var a=n(0),s=r(a),u=n(1),c=r(u),l=n(12),p=r(l),f=n(13),h=r(f),d=function(){function e(t){(0,p.default)(this,e),this.root=i(t||{})}return(0,h.default)(e,[{key:"set",value:function(e,t){var n=this.getParent(e,!0);if(!n)return void o(this.root,t,null);var r=e[e.length-1],a=n.children;return a[r]?void o(a[r],t,n):void(a[r]=i(t,n))}},{key:"get",value:function(e){if(e=e||[],e.length<1)return this.root.value;for(var t=this.root,n=void 0,r=void 0,i=0;i")+"#"+e,s=r.contextTree.get([]).baseDoc;if(t==s&&y(o,e))return!0;var u="",c=n.some(function(e){return u=u+"/"+d(e),i[u]&&i[u].some(function(e){return y(e,a)||y(a,e)})});return!!c||void(i[o]=(i[o]||[]).concat(a))}function g(e,t){function n(e){return j.default.isObject(e)&&(r.indexOf(e)>=0||(0,x.default)(e).some(function(t){return n(e[t])}))}var r=[e];return t.path.reduce(function(e,t){return r.push(e[t]),e[t]},e),n(t.value)}Object.defineProperty(t,"__esModule",{value:!0});var _=n(2),b=r(_),w=n(0),x=r(w),k=n(11),S=r(k),E=n(28),C=r(E),A=n(5),T=r(A),O=n(16),D=r(O),M=n(7),P=r(M),I=n(8),j=r(I),R=n(25),F=r(R),B=new RegExp("^([a-z]+://|//)","i"),N=(0,F.default)("JSONRefError",function(e,t,n){this.originalError=n,(0,T.default)(this,t||{})}),z={},L=new C.default,U={key:"$ref",plugin:function(e,t,n,r){var u=n.slice(0,-1),c=r.getContext(n).baseDoc;if("string"!=typeof e)return new N("$ref: must be a string (JSON-Ref)",{$ref:e,baseDoc:c,fullPath:n});var l=a(e),p=l[0],h=l[1]||"",d=void 0;try{d=c||p?i(p,c):null}catch(t){return o(t,{pointer:h,$ref:e,basePath:d,fullPath:n})}var m=void 0,y=void 0;if(!v(h,d,u,r)){if(null==d?(y=f(h),m=r.get(y),"undefined"==typeof m&&(m=new N("Could not resolve reference: "+e,{pointer:h,$ref:e,baseDoc:c,fullPath:n}))):(m=s(d,h),m=null!=m.__value?m.__value:m.catch(function(t){throw o(t,{pointer:h,$ref:e,baseDoc:c,fullPath:n})})),m instanceof Error)return[j.default.remove(n),m];var _=j.default.replace(u,m,{$$ref:e});return d&&d!==c?[_,j.default.context(u,{baseDoc:d})]:g(r.state,_)?void 0:_}}},q=(0,T.default)(U,{docCache:z,absoluteify:i,clearCache:u,JSONRefError:N,wrapError:o,getDoc:c,split:a,extractFromDoc:s,fetchJSON:l,extract:p,jsonPointerToArray:f,unescapeJsonPointerToken:h});t.default=q;var W=function(e){return!e||"/"===e||"#"===e}},function(e,t){e.exports=n(1036)},function(e,t){e.exports=n(1039)},function(e,t){e.exports=n(1047)},function(e,t){e.exports=n(1048)},function(e,t){e.exports=n(1053)},function(e,t){e.exports=n(1054)},function(e,t){e.exports=n(1055)},function(e,t){e.exports=n(1056)},function(e,t){e.exports=n(1057)},function(e,t){e.exports=n(1092)},function(e,t){e.exports=n(1160)},function(e,t){e.exports=n(1171)},function(e,t){e.exports=n(1179)},function(e,t,n){e.exports=n(18)}])},function(e,t,n){e.exports={default:n(879),__esModule:!0}},function(e,t,n){n(880),e.exports=n(900).Object.keys},[1405,881,883,898],[1403,882],35,[1384,884,897],[1385,885,886,889,893],5,[1386,887,882],[1387,888],34,[1388,886,890,892],[1389,891],38,[1390,891],[1391,894,896],[1378,895],4,19,41,[1402,899,900,909],function(e,t,n){var r=n(895),i=n(900),o=n(901),a=n(903),s="prototype",u=function(e,t,n){var c,l,p,f=e&u.F,h=e&u.G,d=e&u.S,m=e&u.P,y=e&u.B,v=e&u.W,g=h?i:i[t]||(i[t]={}),_=g[s],b=h?r:d?r[t]:(r[t]||{})[s];h&&(n=t);for(c in n)l=!f&&b&&void 0!==b[c],l&&c in g||(p=l?b[c]:n[c],g[c]=h&&"function"!=typeof b[c]?n[c]:y&&l?o(p,r):v&&b[c]==p?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t[s]=e[s],t}(p):m&&"function"==typeof p?o(Function.call,p):p,m&&((g.virtual||(g.virtual={}))[c]=p,e&u.R&&_&&!_[c]&&a(_,c,p)))};u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,e.exports=u},9,[1376,902],21,[1370,904,912,908],[1371,905,907,911,908],[1372,906],13,[1373,908,909,910],[1369,909],7,[1374,906,895],[1375,906],17,function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(914),o=r(i);t.default=o.default||function(e){for(var t=1;t1?n[i-1]:void 0,s=i>2?n[2]:void 0;for(a=e.length>3&&"function"==typeof a?(i--,a):void 0,s&&o(n[0],n[1],s)&&(a=i<3?void 0:a,i=1),t=Object(t);++r0){if(++t>=r)return arguments[0]}else t=0;return e.apply(void 0,arguments);
+}}var r=500,i=16,o=Date.now;e.exports=n},[1473,958,981,983,972],[1464,971,982],432,429,436,[1460,986,992,981],function(e,t,n){function r(e,t){var n=a(e)||o(e)?i(e.length,String):[],r=n.length,u=!!r;for(var l in e)!t&&!c.call(e,l)||u&&("length"==l||s(l,r))||n.push(l);return n}var i=n(987),o=n(988),a=n(991),s=n(983),u=Object.prototype,c=u.hasOwnProperty;e.exports=r},424,function(e,t,n){function r(e){return i(e)&&s.call(e,"callee")&&(!c.call(e,"callee")||u.call(e)==o)}var i=n(989),o="[object Arguments]",a=Object.prototype,s=a.hasOwnProperty,u=a.toString,c=a.propertyIsEnumerable;e.exports=r},function(e,t,n){function r(e){return o(e)&&i(e)}var i=n(981),o=n(990);e.exports=r},316,347,[1462,984,993],[1463,994],315,function(e,t,n){"use strict";function r(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}function i(e,t,n){if(e&&c.isObject(e)&&e instanceof r)return e;var i=new r;return i.parse(e,t,n),i}function o(e){return c.isString(e)&&(e=i(e)),e instanceof r?e.format():r.prototype.format.call(e)}function a(e,t){return i(e,!1,!0).resolve(t)}function s(e,t){return e?i(e,!1,!0).resolveObject(t):t}var u=n(996),c=n(997);t.parse=i,t.resolve=a,t.resolveObject=s,t.format=o,t.Url=r;var l=/^([a-z0-9.+-]+:)/i,p=/:[0-9]*$/,f=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,h=["<",">",'"',"`"," ","\r","\n","\t"],d=["{","}","|","\\","^","`"].concat(h),m=["'"].concat(d),y=["%","/","?",";","#"].concat(m),v=["/","?","#"],g=255,_=/^[+a-z0-9A-Z_-]{0,63}$/,b=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,w={javascript:!0,"javascript:":!0},x={javascript:!0,"javascript:":!0},k={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},S=n(998);r.prototype.parse=function(e,t,n){if(!c.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var r=e.indexOf("?"),i=r!==-1&&r127?"x":j[F];if(!R.match(_)){var N=P.slice(0,A),z=P.slice(A+1),L=j.match(b);L&&(N.push(L[1]),z.unshift(L[2])),z.length&&(s="/"+z.join(".")+s),this.hostname=N.join(".");break}}}this.hostname.length>g?this.hostname="":this.hostname=this.hostname.toLowerCase(),M||(this.hostname=u.toASCII(this.hostname));var U=this.port?":"+this.port:"",q=this.hostname||"";this.host=q+U,this.href+=this.host,M&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==s[0]&&(s="/"+s))}if(!w[d])for(var A=0,I=m.length;A0)&&n.host.split("@");E&&(n.auth=E.shift(),n.host=n.hostname=E.shift())}return n.search=e.search,n.query=e.query,c.isNull(n.pathname)&&c.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!w.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var C=w.slice(-1)[0],A=(n.host||e.host||w.length>1)&&("."===C||".."===C)||""===C,T=0,O=w.length;O>=0;O--)C=w[O],"."===C?w.splice(O,1):".."===C?(w.splice(O,1),T++):T&&(w.splice(O,1),T--);if(!_&&!b)for(;T--;T)w.unshift("..");!_||""===w[0]||w[0]&&"/"===w[0].charAt(0)||w.unshift(""),A&&"/"!==w.join("/").substr(-1)&&w.push("");var D=""===w[0]||w[0]&&"/"===w[0].charAt(0);if(S){n.hostname=n.host=D?"":w.length?w.shift():"";var E=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@");E&&(n.auth=E.shift(),n.host=n.hostname=E.shift())}return _=_||n.host&&w.length,_&&!D&&w.unshift(""),w.length?n.pathname=w.join("/"):(n.pathname=null,n.path=null),c.isNull(n.pathname)&&c.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=e.auth||n.auth,n.slashes=n.slashes||e.slashes,n.href=n.format(),n},r.prototype.parseHost=function(){var e=this.host,t=p.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,n){var r;(function(e,i){!function(o){function a(e){throw RangeError(P[e])}function s(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function u(e,t){var n=e.split("@"),r="";n.length>1&&(r=n[0]+"@",e=n[1]),e=e.replace(M,".");var i=e.split("."),o=s(i,t).join(".");return r+o}function c(e){for(var t,n,r=[],i=0,o=e.length;i=55296&&t<=56319&&i65535&&(e-=65536,t+=R(e>>>10&1023|55296),e=56320|1023&e),t+=R(e)}).join("")}function p(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:w}function f(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function h(e,t,n){var r=0;for(e=n?j(e/E):e>>1,e+=j(e/t);e>I*k>>1;r+=w)e=j(e/I);return j(r+(I+1)*e/(e+S))}function d(e){var t,n,r,i,o,s,u,c,f,d,m=[],y=e.length,v=0,g=A,_=C;for(n=e.lastIndexOf(T),n<0&&(n=0),r=0;r=128&&a("not-basic"),m.push(e.charCodeAt(r));for(i=n>0?n+1:0;i=y&&a("invalid-input"),c=p(e.charCodeAt(i++)),(c>=w||c>j((b-v)/s))&&a("overflow"),v+=c*s,f=u<=_?x:u>=_+k?k:u-_,!(cj(b/d)&&a("overflow"),s*=d;t=m.length+1,_=h(v-o,t,0==o),j(v/t)>b-g&&a("overflow"),g+=j(v/t),v%=t,m.splice(v++,0,g)}return l(m)}function m(e){var t,n,r,i,o,s,u,l,p,d,m,y,v,g,_,S=[];for(e=c(e),y=e.length,t=A,n=0,o=C,s=0;s=t&&mj((b-n)/v)&&a("overflow"),n+=(u-t)*v,t=u,s=0;sb&&a("overflow"),m==t){for(l=n,p=w;d=p<=o?x:p>=o+k?k:p-o,!(l= 0x80 (not a basic code point)","invalid-input":"Invalid input"},I=w-x,j=Math.floor,R=String.fromCharCode;_={version:"1.3.2",ucs2:{decode:c,encode:l},decode:d,encode:m,toASCII:v,toUnicode:y},r=function(){return _}.call(t,n,t,e),!(void 0!==r&&(e.exports=r))}(this)}).call(t,n(319)(e),function(){return this}())},function(e,t){"use strict";e.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},function(e,t,n){"use strict";t.decode=t.parse=n(999),t.encode=t.stringify=n(1e3)},function(e,t){"use strict";function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,r,i){t=t||"&",r=r||"=";var o={};if("string"!=typeof e||0===e.length)return o;var a=/\+/g;e=e.split(t);var s=1e3;i&&"number"==typeof i.maxKeys&&(s=i.maxKeys);var u=e.length;s>0&&u>s&&(u=s);for(var c=0;c=0?(l=d.substr(0,m),p=d.substr(m+1)):(l=d,p=""),f=decodeURIComponent(l),h=decodeURIComponent(p),n(o,f)?Array.isArray(o[f])?o[f].push(h):o[f]=[o[f],h]:o[f]=h}return o}},function(e,t){"use strict";var n=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};e.exports=function(e,t,r,i){return t=t||"&",r=r||"=",null===e&&(e=void 0),"object"==typeof e?Object.keys(e).map(function(i){var o=encodeURIComponent(n(i))+r;return Array.isArray(e[i])?e[i].map(function(e){return o+encodeURIComponent(n(e))}).join(t):o+encodeURIComponent(n(e[i]))}).join(t):i?encodeURIComponent(n(i))+r+encodeURIComponent(n(e)):""}},function(e,t,n){e.exports={default:n(1002),__esModule:!0}},function(e,t,n){n(936),n(923),e.exports=n(1003)},function(e,t,n){var r=n(905),i=n(1004);e.exports=n(900).getIterator=function(e){var t=i(e);if("function"!=typeof t)throw TypeError(e+" is not iterable!");return r(t.call(e))}},[1417,1005,934,928,900],[1408,888,934],function(e,t,n){e.exports={default:n(1007),__esModule:!0}},function(e,t,n){var r=n(900),i=r.JSON||(r.JSON={stringify:JSON.stringify});e.exports=function(e){return i.stringify.apply(i,arguments)}},function(e,t,n){e.exports={default:n(1009),__esModule:!0}},function(e,t,n){n(952),n(923),n(936),n(1010),e.exports=n(900).Promise},[1423,926,895,901,1005,899,906,902,1011,1012,1015,1016,1018,934,1019,933,1020,900,1021],205,[1424,901,1013,1014,905,890,1004],[1414,905],[1415,928,934],[1425,905,902,934],[1426,901,1017,932,910,895,888],78,[1427,895,1016,888],function(e,t,n){var r=n(903);e.exports=function(e,t,n){for(var i in t)n&&e[i]?e[i]=t[i]:r(e,i,t[i]);return e}},function(e,t,n){"use strict";var r=n(895),i=n(900),o=n(904),a=n(908),s=n(934)("species");e.exports=function(e){var t="function"==typeof i[e]?i[e]:r[e];a&&t&&!t[s]&&o.f(t,s,{configurable:!0,get:function(){return this}})}},[1418,934],function(e,t){"use strict";t.__esModule=!0,t.default=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(1024),o=r(i);t.default=function(){function e(e,t){for(var n=0;n=0,o=i&&r.regeneratorRuntime;if(r.regeneratorRuntime=void 0,e.exports=n(1033),i)r.regeneratorRuntime=o;else try{delete r.regeneratorRuntime}catch(e){r.regeneratorRuntime=void 0}}).call(t,function(){return this}())},293,function(e,t,n){n(1035),e.exports=self.fetch.bind(self)},function(e,t){!function(e){"use strict";function t(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(e))throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function n(e){return"string"!=typeof e&&(e=String(e)),e}function r(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return v.iterable&&(t[Symbol.iterator]=function(){return t}),t}function i(e){this.map={},e instanceof i?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}function o(e){return e.bodyUsed?Promise.reject(new TypeError("Already read")):void(e.bodyUsed=!0)}function a(e){return new Promise(function(t,n){e.onload=function(){t(e.result)},e.onerror=function(){n(e.error)}})}function s(e){var t=new FileReader,n=a(t);return t.readAsArrayBuffer(e),n}function u(e){var t=new FileReader,n=a(t);return t.readAsText(e),n}function c(e){for(var t=new Uint8Array(e),n=new Array(t.length),r=0;r-1?t:e}function h(e,t){t=t||{};var n=t.body;if(e instanceof h){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,t.headers||(this.headers=new i(e.headers)),this.method=e.method,this.mode=e.mode,n||null==e._bodyInit||(n=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=t.credentials||this.credentials||"omit",!t.headers&&this.headers||(this.headers=new i(t.headers)),this.method=f(t.method||this.method||"GET"),this.mode=t.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&n)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(n)}function d(e){var t=new FormData;return e.trim().split("&").forEach(function(e){if(e){var n=e.split("="),r=n.shift().replace(/\+/g," "),i=n.join("=").replace(/\+/g," ");t.append(decodeURIComponent(r),decodeURIComponent(i))}}),t}function m(e){var t=new i;return e.split(/\r?\n/).forEach(function(e){var n=e.split(":"),r=n.shift().trim();if(r){var i=n.join(":").trim();t.append(r,i)}}),t}function y(e,t){t||(t={}),this.type="default",this.status="status"in t?t.status:200,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in t?t.statusText:"OK",this.headers=new i(t.headers),this.url=t.url||"",this._initBody(e)}if(!e.fetch){var v={searchParams:"URLSearchParams"in e,iterable:"Symbol"in e&&"iterator"in Symbol,blob:"FileReader"in e&&"Blob"in e&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in e,arrayBuffer:"ArrayBuffer"in e};if(v.arrayBuffer)var g=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],_=function(e){return e&&DataView.prototype.isPrototypeOf(e)},b=ArrayBuffer.isView||function(e){return e&&g.indexOf(Object.prototype.toString.call(e))>-1};i.prototype.append=function(e,r){e=t(e),r=n(r);var i=this.map[e];this.map[e]=i?i+","+r:r},i.prototype.delete=function(e){delete this.map[t(e)]},i.prototype.get=function(e){return e=t(e),this.has(e)?this.map[e]:null},i.prototype.has=function(e){return this.map.hasOwnProperty(t(e))},i.prototype.set=function(e,r){this.map[t(e)]=n(r)},i.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},i.prototype.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),r(e)},i.prototype.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),r(e)},i.prototype.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),r(e)},v.iterable&&(i.prototype[Symbol.iterator]=i.prototype.entries);var w=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];h.prototype.clone=function(){return new h(this,{body:this._bodyInit})},p.call(h.prototype),p.call(y.prototype),y.prototype.clone=function(){return new y(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new i(this.headers),url:this.url})},y.error=function(){var e=new y(null,{status:0,statusText:""});return e.type="error",e};var x=[301,302,303,307,308];y.redirect=function(e,t){if(x.indexOf(t)===-1)throw new RangeError("Invalid status code");return new y(null,{status:t,headers:{location:e}})},e.Headers=i,e.Request=h,e.Response=y,e.fetch=function(e,t){return new Promise(function(n,r){var i=new h(e,t),o=new XMLHttpRequest;o.onload=function(){var e={status:o.status,statusText:o.statusText,headers:m(o.getAllResponseHeaders()||"")};e.url="responseURL"in o?o.responseURL:e.headers.get("X-Request-URL");var t="response"in o?o.response:o.responseText;n(new y(t,e))},o.onerror=function(){r(new TypeError("Network request failed"))},o.ontimeout=function(){r(new TypeError("Network request failed"))},o.open(i.method,i.url,!0),"include"===i.credentials&&(o.withCredentials=!0),"responseType"in o&&v.blob&&(o.responseType="blob"),i.headers.forEach(function(e,t){o.setRequestHeader(t,e)}),o.send("undefined"==typeof i._bodyInit?null:i._bodyInit)})},e.fetch.polyfill=!0}}("undefined"!=typeof self?self:this)},function(e,t,n){e.exports={default:n(1037),__esModule:!0}},function(e,t,n){n(1038);var r=n(900).Object;e.exports=function(e,t){return r.create(e,t)}},[1400,899,930],function(e,t,n){e.exports={default:n(1040),__esModule:!0}},function(e,t,n){n(952),n(936),n(1041),e.exports=n(900).WeakMap},[1428,1042,927,944,917,1045,906,1046],[1419,901,887,881,890,1043],[1420,1044],[1421,906,948,934],[1429,1019,944,905,906,1011,1012,1042,885],function(e,t,n){"use strict";var r=n(895),i=n(899),o=n(944),a=n(909),s=n(903),u=n(1019),c=n(1012),l=n(1011),p=n(906),f=n(933),h=n(904).f,d=n(1042)(0),m=n(908);e.exports=function(e,t,n,y,v,g){var _=r[e],b=_,w=v?"set":"add",x=b&&b.prototype,k={};return m&&"function"==typeof b&&(g||x.forEach&&!a(function(){(new b).entries().next()}))?(b=t(function(t,n){l(t,b,e,"_c"),t._c=new _,void 0!=n&&c(n,v,t[w],t)}),d("add,clear,delete,forEach,get,has,set,keys,values,entries,toJSON".split(","),function(e){var t="add"==e||"set"==e;e in x&&(!g||"clear"!=e)&&s(b.prototype,e,function(n,r){if(l(this,b,e),!t&&g&&!p(n))return"get"==e&&void 0;var i=this._c[e](0===n?0:n,r);return t?this:i})}),"size"in x&&h(b.prototype,"size",{get:function(){return this._c.size}})):(b=y.getConstructor(t,e,v,w),u(b.prototype,n),o.NEED=!0),f(b,e),k[e]=b,i(i.G+i.W+i.F,k),g||y.setStrong(b,e,v),b}},function(e,t){"use strict";t.__esModule=!0,t.default=function(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(1049),o=r(i);t.default=function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t0&&(e.patches=[],e.callback&&e.callback(i)),i}function l(e,t,r,i){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var o=g(t),a=g(e),u=!1,c=!1,p=a.length-1;p>=0;p--){var f=a[p],h=e[f];if(!t.hasOwnProperty(f)||void 0===t[f]&&void 0!==h&&E(t)===!1)r.push({op:"remove",path:i+"/"+n(f)}),c=!0;else{var d=t[f];"object"==typeof h&&null!=h&&"object"==typeof d&&null!=d?l(h,d,r,i+"/"+n(f)):h!==d&&(u=!0,r.push({op:"replace",path:i+"/"+n(f),value:s(d)}))}}if(c||o.length!=a.length)for(var p=0;p=48&&t<=57))return!1;n++}}return!0}function f(e,t,n){for(var r,i,o=[],a=0,s=t.length;a=h){o.push(w[r.op].call(r,l,i,e));break}if(E(l)){if("-"===i)i=l.length;else{if(n&&!p(i))throw new C("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",a-1,r.path,r);i=parseInt(i,10)}if(f>=h){if(n&&"add"===r.op&&i>l.length)throw new C("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",a-1,r.path,r);o.push(b[r.op].call(r,l,i,e));break}}else if(i&&i.indexOf("~")!=-1&&(i=i.replace(/~1/g,"/").replace(/~0/g,"~")),f>=h){o.push(_[r.op].call(r,l,i,e));break}l=l[i]}}return o}function h(e,t){var n=[];return l(e,t,n,""),n}function d(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}function m(e){if(void 0===e)return!0;if("array"==typeof e||"object"==typeof e)for(var t in e)if(m(e[t]))return!0;return!1}function y(t,n,r,i){if("object"!=typeof t||null===t||E(t))throw new C("Operation is not an object","OPERATION_NOT_AN_OBJECT",n,t,r);if(!_[t.op])throw new C("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",n,t,r);if("string"!=typeof t.path)throw new C("Operation `path` property is not a string","OPERATION_PATH_INVALID",n,t,r);if(0!==t.path.indexOf("/")&&t.path.length>0)throw new C('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",n,t,r);if(("move"===t.op||"copy"===t.op)&&"string"!=typeof t.from)throw new C("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",n,t,r);if(("add"===t.op||"replace"===t.op||"test"===t.op)&&void 0===t.value)throw new C("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",n,t,r);if(("add"===t.op||"replace"===t.op||"test"===t.op)&&m(t.value))throw new C("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",n,t,r);if(r)if("add"==t.op){var o=t.path.split("/").length,a=i.split("/").length;if(o!==a+1&&o!==a)throw new C("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",n,t,r)}else if("replace"===t.op||"remove"===t.op||"_get"===t.op){if(t.path!==i)throw new C("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",n,t,r)}else if("move"===t.op||"copy"===t.op){var s={op:"_get",path:t.from,value:void 0},u=e.validate([s],r);if(u&&"OPERATION_PATH_UNRESOLVABLE"===u.name)throw new C("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",n,t,r)}}function v(e,t){try{if(!E(e))throw new C("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(t)t=JSON.parse(JSON.stringify(t)),f.call(this,t,e,!0);else for(var n=0;n1?arguments[1]:"utf8"):a(this,t)):arguments.length>1?new e(t,arguments[1]):new e(t)}function i(t,n){if(t=h(t,n<0?0:0|d(n)),!e.TYPED_ARRAY_SUPPORT)for(var r=0;r>>1;return r&&(t.parent=X),t}function d(e){if(e>=r())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+r().toString(16)+" bytes");return 0|e}function m(t,n){if(!(this instanceof m))return new m(t,n);var r=new e(t,n);return delete r.parent,r}function y(e,t){"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"binary":case"raw":case"raws":return n;case"utf8":case"utf-8":return U(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return K(e).length;default:if(r)return U(e).length;t=(""+t).toLowerCase(),r=!0}}function v(e,t,n){var r=!1;if(t|=0,n=void 0===n||n===1/0?this.length:0|n,e||(e="utf8"),t<0&&(t=0),n>this.length&&(n=this.length),n<=t)return"";for(;;)switch(e){case"hex":return O(this,t,n);case"utf8":case"utf-8":return E(this,t,n);case"ascii":return A(this,t,n);case"binary":return T(this,t,n);case"base64":return S(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return D(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function g(e,t,n,r){n=Number(n)||0;var i=e.length-n;r?(r=Number(r),r>i&&(r=i)):r=i;var o=t.length;if(o%2!==0)throw new Error("Invalid hex string");r>o/2&&(r=o/2);for(var a=0;a239?4:o>223?3:o>191?2:1;if(i+s<=n){var u,c,l,p;switch(s){case 1:o<128&&(a=o);break;case 2:u=e[i+1],128===(192&u)&&(p=(31&o)<<6|63&u,p>127&&(a=p));break;case 3:u=e[i+1],c=e[i+2],128===(192&u)&&128===(192&c)&&(p=(15&o)<<12|(63&u)<<6|63&c,p>2047&&(p<55296||p>57343)&&(a=p));break;case 4:u=e[i+1],c=e[i+2],l=e[i+3],128===(192&u)&&128===(192&c)&&128===(192&l)&&(p=(15&o)<<18|(63&u)<<12|(63&c)<<6|63&l,p>65535&&p<1114112&&(a=p))}}null===a?(a=65533,s=1):a>65535&&(a-=65536,r.push(a>>>10&1023|55296),a=56320|1023&a),r.push(a),i+=s}return C(r)}function C(e){var t=e.length;if(t<=Y)return String.fromCharCode.apply(String,e);for(var n="",r=0;rr)&&(n=r);for(var i="",o=t;on)throw new RangeError("Trying to access beyond buffer length")}function P(t,n,r,i,o,a){if(!e.isBuffer(t))throw new TypeError("buffer must be a Buffer instance");if(n>o||nt.length)throw new RangeError("index out of range")}function I(e,t,n,r){t<0&&(t=65535+t+1);for(var i=0,o=Math.min(e.length-n,2);i>>8*(r?i:1-i)}function j(e,t,n,r){t<0&&(t=4294967295+t+1);for(var i=0,o=Math.min(e.length-n,4);i>>8*(r?i:3-i)&255}function R(e,t,n,r,i,o){if(t>i||te.length)throw new RangeError("index out of range");if(n<0)throw new RangeError("index out of range")}function F(e,t,n,r,i){return i||R(e,t,n,4,3.4028234663852886e38,-3.4028234663852886e38),J.write(e,t,n,r,23,4),n+4}function B(e,t,n,r,i){return i||R(e,t,n,8,1.7976931348623157e308,-1.7976931348623157e308),J.write(e,t,n,r,52,8),n+8}function N(e){if(e=z(e).replace(Z,""),e.length<2)return"";for(;e.length%4!==0;)e+="=";return e}function z(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function L(e){return e<16?"0"+e.toString(16):e.toString(16)}function U(e,t){t=t||1/0;for(var n,r=e.length,i=null,o=[],a=0;a55295&&n<57344){if(!i){if(n>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&o.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&o.push(239,191,189),i=n;continue}n=i-55296<<10|n-56320|65536}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;o.push(n)}else if(n<2048){if((t-=2)<0)break;o.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function q(e){for(var t=[],n=0;n>8,i=n%256,o.push(i),o.push(r);return o}function K(e){return H.toByteArray(N(e))}function V(e,t,n,r){for(var i=0;i=t.length||i>=e.length);i++)t[i+n]=e[i];return i}/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh
+ * @license MIT
+ */
+var H=n(1080),J=n(1081),G=n(1082);t.Buffer=e,t.SlowBuffer=m,t.INSPECT_MAX_BYTES=50,e.poolSize=8192;var X={};e.TYPED_ARRAY_SUPPORT=function(){function e(){}try{var t=new Uint8Array(1);return t.foo=function(){return 42},t.constructor=e,42===t.foo()&&t.constructor===e&&"function"==typeof t.subarray&&0===t.subarray(1,1).byteLength}catch(e){return!1}}(),e.isBuffer=function(e){return!(null==e||!e._isBuffer)},e.compare=function(t,n){if(!e.isBuffer(t)||!e.isBuffer(n))throw new TypeError("Arguments must be Buffers");if(t===n)return 0;for(var r=t.length,i=n.length,o=0,a=Math.min(r,i);o0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},e.prototype.compare=function(t){if(!e.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t?0:e.compare(this,t)},e.prototype.indexOf=function(t,n){function r(e,t,n){for(var r=-1,i=0;n+i2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n>>=0,0===this.length)return-1;if(n>=this.length)return-1;if(n<0&&(n=Math.max(this.length+n,0)),"string"==typeof t)return 0===t.length?-1:String.prototype.indexOf.call(this,t,n);if(e.isBuffer(t))return r(this,t,n);if("number"==typeof t)return e.TYPED_ARRAY_SUPPORT&&"function"===Uint8Array.prototype.indexOf?Uint8Array.prototype.indexOf.call(this,t,n):r(this,[t],n);throw new TypeError("val must be string, number or Buffer")},e.prototype.get=function(e){return console.log(".get() is deprecated. Access using array indexes instead."),this.readUInt8(e)},e.prototype.set=function(e,t){return console.log(".set() is deprecated. Access using array indexes instead."),this.writeUInt8(e,t)},e.prototype.write=function(e,t,n,r){if(void 0===t)r="utf8",n=this.length,t=0;else if(void 0===n&&"string"==typeof t)r=t,n=this.length,t=0;else if(isFinite(t))t|=0,isFinite(n)?(n|=0,void 0===r&&(r="utf8")):(r=n,n=void 0);else{var i=r;r=t,t=0|n,n=i}var o=this.length-t;if((void 0===n||n>o)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("attempt to write outside buffer bounds");r||(r="utf8");for(var a=!1;;)switch(r){case"hex":return g(this,e,t,n);case"utf8":case"utf-8":return _(this,e,t,n);case"ascii":return b(this,e,t,n);case"binary":return w(this,e,t,n);case"base64":return x(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return k(this,e,t,n);default:if(a)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},e.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var Y=4096;e.prototype.slice=function(t,n){var r=this.length;t=~~t,n=void 0===n?r:~~n,t<0?(t+=r,t<0&&(t=0)):t>r&&(t=r),n<0?(n+=r,n<0&&(n=0)):n>r&&(n=r),n0&&(i*=256);)r+=this[e+--t]*i;return r},e.prototype.readUInt8=function(e,t){return t||M(e,1,this.length),this[e]},e.prototype.readUInt16LE=function(e,t){return t||M(e,2,this.length),this[e]|this[e+1]<<8},e.prototype.readUInt16BE=function(e,t){return t||M(e,2,this.length),this[e]<<8|this[e+1]},e.prototype.readUInt32LE=function(e,t){return t||M(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},e.prototype.readUInt32BE=function(e,t){return t||M(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},e.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||M(e,t,this.length);for(var r=this[e],i=1,o=0;++o=i&&(r-=Math.pow(2,8*t)),r},e.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||M(e,t,this.length);for(var r=t,i=1,o=this[e+--r];r>0&&(i*=256);)o+=this[e+--r]*i;return i*=128,o>=i&&(o-=Math.pow(2,8*t)),o},e.prototype.readInt8=function(e,t){return t||M(e,1,this.length),128&this[e]?(255-this[e]+1)*-1:this[e]},e.prototype.readInt16LE=function(e,t){t||M(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},e.prototype.readInt16BE=function(e,t){t||M(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},e.prototype.readInt32LE=function(e,t){return t||M(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},e.prototype.readInt32BE=function(e,t){return t||M(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},e.prototype.readFloatLE=function(e,t){return t||M(e,4,this.length),J.read(this,e,!0,23,4)},e.prototype.readFloatBE=function(e,t){return t||M(e,4,this.length),J.read(this,e,!1,23,4)},e.prototype.readDoubleLE=function(e,t){return t||M(e,8,this.length),J.read(this,e,!0,52,8)},e.prototype.readDoubleBE=function(e,t){return t||M(e,8,this.length),J.read(this,e,!1,52,8)},e.prototype.writeUIntLE=function(e,t,n,r){e=+e,t|=0,n|=0,r||P(this,e,t,n,Math.pow(2,8*n),0);var i=1,o=0;for(this[t]=255&e;++o=0&&(o*=256);)this[t+i]=e/o&255;return t+n},e.prototype.writeUInt8=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,1,255,0),e.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[n]=t,n+1},e.prototype.writeUInt16LE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,2,65535,0),e.TYPED_ARRAY_SUPPORT?(this[n]=t,this[n+1]=t>>>8):I(this,t,n,!0),n+2},e.prototype.writeUInt16BE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,2,65535,0),e.TYPED_ARRAY_SUPPORT?(this[n]=t>>>8,this[n+1]=t):I(this,t,n,!1),n+2},e.prototype.writeUInt32LE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,4,4294967295,0),e.TYPED_ARRAY_SUPPORT?(this[n+3]=t>>>24,this[n+2]=t>>>16,this[n+1]=t>>>8,this[n]=t):j(this,t,n,!0),n+4},e.prototype.writeUInt32BE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,4,4294967295,0),e.TYPED_ARRAY_SUPPORT?(this[n]=t>>>24,this[n+1]=t>>>16,this[n+2]=t>>>8,this[n+3]=t):j(this,t,n,!1),n+4},e.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);P(this,e,t,n,i-1,-i)}var o=0,a=1,s=e<0?1:0;for(this[t]=255&e;++o>0)-s&255;return t+n},e.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);P(this,e,t,n,i-1,-i)}var o=n-1,a=1,s=e<0?1:0;for(this[t+o]=255&e;--o>=0&&(a*=256);)this[t+o]=(e/a>>0)-s&255;return t+n},e.prototype.writeInt8=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,1,127,-128),e.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[n]=t,n+1},e.prototype.writeInt16LE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,2,32767,-32768),e.TYPED_ARRAY_SUPPORT?(this[n]=t,this[n+1]=t>>>8):I(this,t,n,!0),n+2},e.prototype.writeInt16BE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,2,32767,-32768),e.TYPED_ARRAY_SUPPORT?(this[n]=t>>>8,this[n+1]=t):I(this,t,n,!1),n+2},e.prototype.writeInt32LE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,4,2147483647,-2147483648),e.TYPED_ARRAY_SUPPORT?(this[n]=t,this[n+1]=t>>>8,this[n+2]=t>>>16,this[n+3]=t>>>24):j(this,t,n,!0),n+4},e.prototype.writeInt32BE=function(t,n,r){return t=+t,n|=0,r||P(this,t,n,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),e.TYPED_ARRAY_SUPPORT?(this[n]=t>>>24,this[n+1]=t>>>16,this[n+2]=t>>>8,this[n+3]=t):j(this,t,n,!1),n+4},e.prototype.writeFloatLE=function(e,t,n){return F(this,e,t,!0,n)},e.prototype.writeFloatBE=function(e,t,n){return F(this,e,t,!1,n)},e.prototype.writeDoubleLE=function(e,t,n){return B(this,e,t,!0,n)},e.prototype.writeDoubleBE=function(e,t,n){return B(this,e,t,!1,n)},e.prototype.copy=function(t,n,r,i){if(r||(r=0),i||0===i||(i=this.length),n>=t.length&&(n=t.length),n||(n=0),i>0&&i=this.length)throw new RangeError("sourceStart out of bounds");if(i<0)throw new RangeError("sourceEnd out of bounds");i>this.length&&(i=this.length),t.length-n=0;o--)t[o+n]=this[o+r];else if(a<1e3||!e.TYPED_ARRAY_SUPPORT)for(o=0;o=this.length)throw new RangeError("start out of bounds");if(n<0||n>this.length)throw new RangeError("end out of bounds");var r;if("number"==typeof e)for(r=t;r0)throw new Error("Invalid string. Length must be a multiple of 4");var l=e.length;u="="===e.charAt(l-2)?2:"="===e.charAt(l-1)?1:0,c=new o(3*e.length/4-u),a=u>0?e.length-4:e.length;var p=0;for(r=0,i=0;r>16),n((65280&s)>>8),n(255&s);return 2===u?(s=t(e.charAt(r))<<2|t(e.charAt(r+1))>>4,n(255&s)):1===u&&(s=t(e.charAt(r))<<10|t(e.charAt(r+1))<<4|t(e.charAt(r+2))>>2,n(s>>8&255),n(255&s)),c}function i(e){function t(e){return r.charAt(e)}function n(e){return t(e>>18&63)+t(e>>12&63)+t(e>>6&63)+t(63&e)}var i,o,a,s=e.length%3,u="";for(i=0,a=e.length-s;i>2),u+=t(o<<4&63),u+="==";break;case 2:o=(e[e.length-2]<<8)+e[e.length-1],u+=t(o>>10),u+=t(o>>4&63),u+=t(o<<2&63),u+="="}return u}var o="undefined"!=typeof Uint8Array?Uint8Array:Array,a="+".charCodeAt(0),s="/".charCodeAt(0),u="0".charCodeAt(0),c="a".charCodeAt(0),l="A".charCodeAt(0),p="-".charCodeAt(0),f="_".charCodeAt(0);e.toByteArray=n,e.fromByteArray=i}(t)},302,function(e,t){var n=Array.isArray,r=Object.prototype.toString;e.exports=n||function(e){return!!e&&"[object Array]"==r.call(e)}},[1494,1065],[1495,1065],[1496,1065],[1497,1064,1063,1087,1088,1089],[1498,1065],[1499,1065],[1500,1090,1065],610,[1501,1060,1061,1086,1063],function(e,t,n){function r(e){return i(e,!0,!0)}var i=n(1093);e.exports=r},function(e,t,n){function r(e,t,n,w,x,k,S){var A;if(w&&(A=k?w(e,x,k,S):w(e)),void 0!==A)return A;if(!g(e))return e;var T=y(e);if(T){if(A=h(e),!t)return c(e,A)}else{var D=f(e),M=D==E||D==C;if(v(e))return u(e,t);if(D==O||D==b||M&&!k){if(A=m(M?{}:e),!t)return l(e,s(A,e))}else{if(!H[D])return k?e:{};A=d(e,D,r,t)}}S||(S=new i);var P=S.get(e);if(P)return P;if(S.set(e,A),!T)var I=n?p(e):_(e);return o(I||e,function(i,o){I&&(o=i,i=e[o]),a(A,o,r(i,t,n,w,o,e,S))}),A}var i=n(1094),o=n(1123),a=n(956),s=n(1124),u=n(1125),c=n(1126),l=n(1127),p=n(1130),f=n(1133),h=n(1139),d=n(1140),m=n(1155),y=n(991),v=n(1158),g=n(972),_=n(985),b="[object Arguments]",w="[object Array]",x="[object Boolean]",k="[object Date]",S="[object Error]",E="[object Function]",C="[object GeneratorFunction]",A="[object Map]",T="[object Number]",O="[object Object]",D="[object RegExp]",M="[object Set]",P="[object String]",I="[object Symbol]",j="[object WeakMap]",R="[object ArrayBuffer]",F="[object DataView]",B="[object Float32Array]",N="[object Float64Array]",z="[object Int8Array]",L="[object Int16Array]",U="[object Int32Array]",q="[object Uint8Array]",W="[object Uint8ClampedArray]",K="[object Uint16Array]",V="[object Uint32Array]",H={};H[b]=H[w]=H[R]=H[F]=H[x]=H[k]=H[B]=H[N]=H[z]=H[L]=H[U]=H[A]=H[T]=H[O]=H[D]=H[M]=H[P]=H[I]=H[q]=H[W]=H[K]=H[V]=!0,H[S]=H[E]=H[j]=!1,e.exports=r},[1456,1095,1102,1103,1104,1105,1106],function(e,t,n){function r(e){var t=-1,n=e?e.length:0;for(this.clear();++t=48&&o<=57||o>=65&&o<=90||o>=97&&o<=122?n+=t.charAt(i):o<128?n+=r[o]:o<2048?n+=r[192|o>>6]+r[128|63&o]:o<55296||o>=57344?n+=r[224|o>>12]+r[128|o>>6&63]+r[128|63&o]:(i+=1,o=65536+((1023&o)<<10|1023&t.charCodeAt(i)),n+=r[240|o>>18]+r[128|o>>12&63]+r[128|o>>6&63]+r[128|63&o])}return n},t.compact=function(e,n){if("object"!=typeof e||null===e)return e;var r=n||[],i=r.indexOf(e);if(i!==-1)return r[i];if(r.push(e),Array.isArray(e)){for(var o=[],a=0;a