turash/bugulma/backend/internal/service/public_transport_importer.go
2025-12-15 10:06:41 +01:00

117 lines
2.8 KiB
Go

package service
import (
"context"
"encoding/csv"
"fmt"
"io"
"log"
"strings"
"bugulma/backend/internal/domain"
)
// ImportPublicTransportData imports stops and routes from the service's loaded files into repository
func ImportPublicTransportData(ctx context.Context, svc *PublicTransportService, repo domain.PublicTransportRepository) error {
if svc == nil || repo == nil {
return nil // nothing to do
}
// Seed common stops from enriched JSON if available
if cs := svc.ListStops(); len(cs) > 0 {
for key, v := range cs {
m, ok := v.(map[string]interface{})
if !ok {
continue
}
stop := &domain.PublicTransportStop{ID: key}
if name, ok := m["name"].(string); ok {
stop.Name = name
}
if nameEn, ok := m["name_en"].(string); ok {
stop.NameEn = nameEn
}
if typ, ok := m["type"].(string); ok {
stop.Type = typ
}
if addr, ok := m["address"].(string); ok {
stop.Address = addr
}
if osm, ok := m["osm_id"].(string); ok {
stop.OsmID = osm
}
if est, ok := m["estimated"].(bool); ok {
stop.Estimated = est
}
if loc, ok := m["location"].(map[string]interface{}); ok {
if lat, ok := loc["lat"].(float64); ok {
stop.Latitude = &lat
}
if lng, ok := loc["lng"].(float64); ok {
stop.Longitude = &lng
}
}
if routes, ok := m["routes_served"].([]interface{}); ok {
for _, r := range routes {
if s, ok := r.(string); ok {
stop.RoutesServed = append(stop.RoutesServed, s)
}
}
}
if err := repo.UpsertStop(ctx, stop); err != nil {
log.Printf("warning: failed to upsert stop %s: %v", stop.ID, err)
}
}
}
// Seed GTFS routes from routes.txt
if routesCSV, err := svc.ReadGTFSFile("routes.txt"); err == nil {
r := csv.NewReader(strings.NewReader(routesCSV))
// Read header
header, err := r.Read()
if err == nil {
idx := map[string]int{}
for i, h := range header {
idx[h] = i
}
for {
rec, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("failed to read routes CSV: %w", err)
}
id := rec[idx["route_id"]]
rt := &domain.PublicTransportRoute{ID: id}
if v, ok := idx["agency_id"]; ok {
rt.AgencyID = rec[v]
}
if v, ok := idx["route_short_name"]; ok {
rt.ShortName = rec[v]
}
if v, ok := idx["route_long_name"]; ok {
rt.LongName = rec[v]
}
if v, ok := idx["route_type"]; ok {
if rec[v] != "" {
// parse int route_type
// we keep it simple and ignore parse errors
var rtType int
fmt.Sscanf(rec[v], "%d", &rtType)
rt.RouteType = rtType
}
}
if err := repo.UpsertRoute(ctx, rt); err != nil {
log.Printf("warning: failed to upsert route %s: %v", rt.ID, err)
}
}
}
} else {
// Missing routes file is fine
}
return nil
}