Files
cmr-mini/backend/internal/service/preview_contract.go

223 lines
5.9 KiB
Go

package service
import "strings"
type MapPreviewView struct {
Mode string `json:"mode"`
BaseTiles *PreviewBaseTiles `json:"baseTiles,omitempty"`
Viewport *PreviewViewport `json:"viewport,omitempty"`
Variants []PreviewVariantView `json:"variants,omitempty"`
SelectedVariantID *string `json:"selectedVariantId,omitempty"`
}
type PreviewBaseTiles struct {
TileBaseURL string `json:"tileBaseUrl"`
Zoom *int `json:"zoom,omitempty"`
TileSize *int `json:"tileSize,omitempty"`
}
type PreviewViewport struct {
Width *int `json:"width,omitempty"`
Height *int `json:"height,omitempty"`
MinLon *float64 `json:"minLon,omitempty"`
MinLat *float64 `json:"minLat,omitempty"`
MaxLon *float64 `json:"maxLon,omitempty"`
MaxLat *float64 `json:"maxLat,omitempty"`
}
type PreviewVariantView struct {
VariantID string `json:"variantId"`
Name *string `json:"name,omitempty"`
RouteCode *string `json:"routeCode,omitempty"`
Controls []PreviewControlView `json:"controls,omitempty"`
Legs []PreviewLegView `json:"legs,omitempty"`
}
type PreviewControlView struct {
ID string `json:"id"`
Kind *string `json:"kind,omitempty"`
Lon *float64 `json:"lon,omitempty"`
Lat *float64 `json:"lat,omitempty"`
Label *string `json:"label,omitempty"`
}
type PreviewLegView struct {
From string `json:"from"`
To string `json:"to"`
}
func buildPreviewFromPayload(payloadJSON *string) (*MapPreviewView, error) {
if payloadJSON == nil || strings.TrimSpace(*payloadJSON) == "" {
return nil, nil
}
payload, err := decodeJSONObject(*payloadJSON)
if err != nil {
return nil, err
}
rawPreview, _ := payload["preview"].(map[string]any)
if len(rawPreview) == 0 {
return nil, nil
}
view := &MapPreviewView{}
if mode := readStringField(rawPreview, "mode"); mode != nil {
view.Mode = *mode
}
if view.Mode == "" {
view.Mode = "readonly"
}
if rawBaseTiles, ok := rawPreview["baseTiles"].(map[string]any); ok && len(rawBaseTiles) > 0 {
baseTiles := &PreviewBaseTiles{}
if tileBaseURL := readStringField(rawBaseTiles, "tileBaseUrl"); tileBaseURL != nil {
baseTiles.TileBaseURL = *tileBaseURL
}
baseTiles.Zoom = readIntField(rawBaseTiles, "zoom")
baseTiles.TileSize = readIntField(rawBaseTiles, "tileSize")
if strings.TrimSpace(baseTiles.TileBaseURL) != "" {
view.BaseTiles = baseTiles
}
}
if rawViewport, ok := rawPreview["viewport"].(map[string]any); ok && len(rawViewport) > 0 {
viewport := &PreviewViewport{
Width: readIntField(rawViewport, "width"),
Height: readIntField(rawViewport, "height"),
MinLon: readFloatField(rawViewport, "minLon"),
MinLat: readFloatField(rawViewport, "minLat"),
MaxLon: readFloatField(rawViewport, "maxLon"),
MaxLat: readFloatField(rawViewport, "maxLat"),
}
view.Viewport = viewport
}
if selectedVariantID := readStringField(rawPreview, "selectedVariantId"); selectedVariantID != nil {
view.SelectedVariantID = selectedVariantID
}
rawVariants, _ := rawPreview["variants"].([]any)
if len(rawVariants) > 0 {
view.Variants = make([]PreviewVariantView, 0, len(rawVariants))
for _, raw := range rawVariants {
item, ok := raw.(map[string]any)
if !ok {
continue
}
variantID := readStringField(item, "variantId")
if variantID == nil || strings.TrimSpace(*variantID) == "" {
variantID = readStringField(item, "id")
}
if variantID == nil || strings.TrimSpace(*variantID) == "" {
continue
}
variant := PreviewVariantView{
VariantID: *variantID,
Name: readStringField(item, "name"),
RouteCode: readStringField(item, "routeCode"),
}
rawControls, _ := item["controls"].([]any)
if len(rawControls) > 0 {
variant.Controls = make([]PreviewControlView, 0, len(rawControls))
for _, rawControl := range rawControls {
controlMap, ok := rawControl.(map[string]any)
if !ok {
continue
}
controlID := readStringField(controlMap, "id")
if controlID == nil || strings.TrimSpace(*controlID) == "" {
continue
}
variant.Controls = append(variant.Controls, PreviewControlView{
ID: *controlID,
Kind: readStringField(controlMap, "kind"),
Lon: readFloatField(controlMap, "lon"),
Lat: readFloatField(controlMap, "lat"),
Label: readStringField(controlMap, "label"),
})
}
}
rawLegs, _ := item["legs"].([]any)
if len(rawLegs) > 0 {
variant.Legs = make([]PreviewLegView, 0, len(rawLegs))
for _, rawLeg := range rawLegs {
legMap, ok := rawLeg.(map[string]any)
if !ok {
continue
}
from := readStringField(legMap, "from")
to := readStringField(legMap, "to")
if from == nil || to == nil || strings.TrimSpace(*from) == "" || strings.TrimSpace(*to) == "" {
continue
}
variant.Legs = append(variant.Legs, PreviewLegView{
From: *from,
To: *to,
})
}
}
view.Variants = append(view.Variants, variant)
}
}
if view.BaseTiles == nil && view.Viewport == nil && len(view.Variants) == 0 {
return nil, nil
}
return view, nil
}
func readIntField(object map[string]any, key string) *int {
if object == nil {
return nil
}
value, ok := object[key]
if !ok {
return nil
}
switch v := value.(type) {
case int:
result := v
return &result
case int32:
result := int(v)
return &result
case int64:
result := int(v)
return &result
case float64:
result := int(v)
return &result
default:
return nil
}
}
func readFloatField(object map[string]any, key string) *float64 {
if object == nil {
return nil
}
value, ok := object[key]
if !ok {
return nil
}
switch v := value.(type) {
case float64:
result := v
return &result
case float32:
result := float64(v)
return &result
case int:
result := float64(v)
return &result
case int32:
result := float64(v)
return &result
case int64:
result := float64(v)
return &result
default:
return nil
}
}