package handler import ( "errors" "time" "git.coopgo.io/coopgo-platform/carpool-service/internal" "git.coopgo.io/coopgo-platform/carpool-service/tiles" "git.coopgo.io/coopgo-platform/routing-service/encoding/polylines" "github.com/google/uuid" "github.com/paulmach/orb" "github.com/paulmach/orb/geojson" "github.com/paulmach/orb/simplify" "github.com/rs/zerolog/log" ) // CreateRegularRoutes creates and stores a regular route func (h *CarpoolServiceHandler) CreateRegularRoutes(routes []*geojson.FeatureCollection) error { groupid := uuid.NewString() for _, r := range routes { r.ExtraMembers["id"] = uuid.NewString() r.ExtraMembers["routes_group_id"] = groupid properties, ok := r.ExtraMembers["properties"].(map[string]any) if !ok { return errors.New("no properties found in feature collection") } polyline, ok := properties["polyline"].(string) if !ok { return errors.New("no polyline found in properties from feature collection") } linestring := polylines.Decode(&polyline, 5) simplified_linestring := simplify.DouglasPeucker(0.003).Simplify(linestring.Clone()) // Simplification tests // Antibes -> Rennes // Without Simplify : 12230 // 0.01 -> 129 // 0.005 -> 230 // 0.003 -> 338 lsFeature := geojson.NewFeature(simplified_linestring) lsFeature.Properties["encoded_polyline"] = polyline r.Append(lsFeature) gridids := tiles.LineStringGridIds(simplified_linestring.(orb.LineString)) r.ExtraMembers["grid_ids"] = gridids } if err := h.Storage.CreateRegularRoutes(routes); err != nil { return err } return nil } // GetUserPlanning returns the planned routes for a user between 2 dates. It transforms regular routes to multiple indivual planned route schedules func (h *CarpoolServiceHandler) GetUserPlanning(userid string, minDepartureDate time.Time, maxDepartureDate time.Time) (planned_schedules map[string][]internal.PlannedRouteSchedule, missing_planning bool, err error) { log.Debug(). Str("user_id", userid). Time("min_departure_date", minDepartureDate). Time("max_departure_date", maxDepartureDate). Msg("carpool service handler - GetUserPlanning") results := map[string][]internal.PlannedRouteSchedule{} current_date := minDepartureDate for current_date.Before(maxDepartureDate) { results[current_date.Format("2006-01-02")] = []internal.PlannedRouteSchedule{} current_date = current_date.Add(24 * time.Hour) } routes, err := h.Storage.GetUserRegularRoutes(userid) if err != nil { log.Error().Err(err).Msg("error in storage - GetUserRegularRoutes") return nil, false, err } if len(routes) == 0 { return results, true, nil } all_schedules := []internal.PlannedRouteSchedule{} for _, r := range routes { rr := internal.RegularRoute(*r) schedules, err := rr.PlannedRouteSchedules(minDepartureDate, maxDepartureDate) if err != nil { log.Error().Err(err).Msg("PlannedRouteSchedules error") return nil, false, err } all_schedules = append(all_schedules, schedules...) for _, s := range schedules { log.Debug(). Str("route id", s.Route.ExtraMembers.MustString("id")). Any("datetime", s.DepartureDate.Format(time.RFC3339)). Msg("new schedule") dateString := s.DepartureDate.Format("2006-01-02") results[dateString] = append(results[dateString], s) } } if len(all_schedules) > 0 { err = h.Storage.StoreRouteSchedules(all_schedules) if err != nil { log.Error().Err(err).Msg("could not store route schedules") return nil, false, err } } return results, false, nil } // GetPlannedTrip returns a planned trip, given an ID. This should be called after getting the user planning from regular routes func (h *CarpoolServiceHandler) GetPlannedTrip(id string) (*internal.PlannedRouteSchedule, error) { planned_trip, err := h.Storage.GetRouteSchedule(id) if err != nil { log.Error().Str("planned trip id", id).Err(err).Msg("could not retrieve planned schedule") return nil, err } return planned_trip, nil }