using Manager.DTOs; using ManagerService.DTOs; using ManagerService.Helpers; using NetTopologySuite.Geometries; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using static ManagerService.Data.SectionText; namespace ManagerService.Data.SubSection { /// /// Section map /// public class SectionMap : Section { public int MapZoom { get; set; } // Default = 18 public bool IsListViewEnabled { get; set; } = false; public MapTypeApp? MapMapType { get; set; } // Default = Hybrid for Google public MapTypeMapBox? MapTypeMapbox { get; set; } // Default = standard for MapBox public MapProvider? MapMapProvider { get; set; } // Default = Google public List MapPoints { get; set; } public string IconResourceId { get; set; } public Resource IconResource { get; set; } // Icon [Required] [Column(TypeName = "jsonb")] public List MapCategories { get; set; } public string MapCenterLatitude { get; set; } // Center on public string MapCenterLongitude { get; set; } // Center on public override string GetEmbeddableText(string language) => JoinText(new[] { BaseText(language) } .Concat((MapCategories ?? new List()) .OrderBy(c => c.order ?? 0) .Select(c => Translate(c.label, language))) .Concat((MapPoints ?? new List()) .Select(p => p.GetEmbeddableText(language))) .ToArray()); public override IEnumerable GetReferencedResourceIds(string language = null) => BaseResourceIds() .Concat(ResourceId(IconResourceId)) .Concat((MapCategories ?? new List()) .SelectMany(c => ResourceId(c.resourceDTO?.id))) .Concat((MapPoints ?? new List()) .SelectMany(p => p.GetReferencedResourceIds())); public MapDTO ToDTO() { return new MapDTO() { id = Id, label = Label, title = Title.ToList(), description = Description.ToList(), order = Order, type = Type, imageId = ImageId, imageSource = ImageSource, configurationId = ConfigurationId, isSubSection = IsSubSection, parentId = ParentId, dateCreation = DateCreation, instanceId = InstanceId, isBeacon = IsBeacon, beaconId = BeaconId, latitude = Latitude, longitude = Longitude, meterZoneGPS = MeterZoneGPS, zoom = MapZoom, mapType = MapMapType, mapTypeMapbox = MapTypeMapbox, mapProvider = MapMapProvider, iconResourceId = IconResourceId, categories = MapCategories, centerLatitude = MapCenterLatitude, centerLongitude = MapCenterLongitude }; } } public class GeoPoint { [Required] public int? Id { get; set; } [Required] [Column(TypeName = "jsonb")] public List Title { get; set; } [Required] [Column(TypeName = "jsonb")] public List Description { get; set; } [Required] [Column(TypeName = "jsonb")] public List Contents { get; set; } public int? CategorieId { get; set; } public Geometry Geometry { get; set; } public string PolyColor { get; set; } // color of the polyline or polygon public string ImageResourceId { get; set; } public string ImageUrl { get; set; } [Required] [Column(TypeName = "jsonb")] public List Schedules { get; set; } [Required] [Column(TypeName = "jsonb")] public List Prices { get; set; } [Required] [Column(TypeName = "jsonb")] public List Phone { get; set; } [Required] [Column(TypeName = "jsonb")] public List Email { get; set; } [Required] [Column(TypeName = "jsonb")] public List Site { get; set; } public string? SectionMapId { get; set; } [ForeignKey(nameof(SectionMapId))] public SectionMap? SectionMap { get; set; } public string? SectionEventId { get; set; } [ForeignKey(nameof(SectionEventId))] public SectionEvent? SectionEvent { get; set; } public string? SectionScene3DId { get; set; } [ForeignKey(nameof(SectionScene3DId))] public SectionScene3D? SectionScene3D { get; set; } /// /// Position du point sur un modèle 3D, quand il en décore un — à côté du /// PostGIS, qui reste la position sur une carte. /// /// C'est toute l'économie du lot E7 : un point d'intérêt sur une maquette porte /// déjà titre, description, image, contenus audio et multilingue. Il ne lui /// manquait qu'un endroit où se tenir. /// [Column(TypeName = "jsonb")] public Position3D? LocalTransform { get; set; } public string GetEmbeddableText(string language) => JoinText(Translate(Title, language), Translate(Description, language), TranslateContents(Contents, language), Translate(Schedules, language), Translate(Prices, language), Translate(Phone, language), Translate(Email, language), Translate(Site, language)); public IEnumerable GetReferencedResourceIds() => ResourceId(ImageResourceId).Concat(ResourceIds(Contents)); public GeoPointDTO ToDTO() { return new GeoPointDTO { id = Id, title = Title, description = Description, contents = Contents, categorieId = CategorieId, geometry = Geometry != null ? Geometry.ToDto() : null, polyColor = PolyColor, imageResourceId = ImageResourceId, imageUrl = ImageUrl, schedules = Schedules, prices = Prices, phone = Phone, email = Email, site = Site, sectionMapId = SectionMapId, sectionEventId = SectionEventId, sectionScene3DId = SectionScene3DId, localTransform = LocalTransform }; } } /// /// Une position dans un modèle 3D, dans le repère du modèle lui-même — pas dans celui /// du monde. Un point posé sur une maquette doit rester au même endroit de la maquette /// quand on la déplace, l'oriente ou la change d'échelle. /// /// ⚠️ Convention glTF, celle du fichier, pas celle d'Unity : Y vers le haut, /// Z vers l'arrière, main droite. La conversion vit dans un seul endroit côté /// casque (GltfSpace), et c'est exprès — un miroir d'axes est invisible sur une /// maquette symétrique et se paie très cher découvert tard. /// public class Position3D { public float x { get; set; } public float y { get; set; } public float z { get; set; } /// Rotation en degrés autour de Y. Sert à orienter un panneau vers l'allée. public float? rotationY { get; set; } } // SectionMap "normal" comme avant => Via geopoints. Si il y a des guidedPath lié à la sectionMap alors il y a un parcours lié à la sectionMap, tu peux aussi avoir des geopoints classique mis là + des parcours. et aussi lier un guidedstep à un geopoint (pour le trigger et aussi pour "afficher plus") }