using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using TMPro; using Unity.VisualScripting; using UnityEngine; public class StoreLocatorUI : MonoBehaviour { [Header("Références UI")] public TMP_InputField postalCodeField; // ton TMP PostalCodeField public TMP_Dropdown dropdown; // ton Dropdown pour afficher les magasins [Header("FSA Locator")] public FsaLocator fsaLocator; // réf. à ton composant FsaLocator dans la scène [Header("Config")] public int maxResults = 5; // nombre de magasins à afficher (5) [Serializable] private class StoreDistance { public string town; public string name; public string lineRaw; // la ligne brute de _G.UIT_LibraryStores si tu veux la réutiliser public double distanceKm; } // Appelé par le bouton SearchPC (OnClick) public void OnSearchPostalCode() { string pc = postalCodeField != null ? postalCodeField.text : string.Empty; if (string.IsNullOrWhiteSpace(pc)) { Debug.LogWarning("StoreLocatorUI: code postal vide."); return; } // 1) Récupérer la position approximative du client via le FSA if (!fsaLocator.TryGetLatLonFromPostal(pc, out double userLat, out double userLon)) { Debug.LogWarning("StoreLocatorUI: impossible de trouver les coordonnées pour le code postal: " + pc); ClearDropdown("Aucun magasin trouvé (code postal invalide)"); return; } // 2) Construire une liste (distance, magasin) List distances = ComputeStoreDistances(userLat, userLon); //print() if (distances == null || distances.Count == 0) { ClearDropdown("Aucun magasin disponible " +distances.Count); return; } // 3) Trier par distance var closest = distances .OrderBy(s => s.distanceKm) .Take(maxResults) .ToList(); // 4) Remplir le Dropdown dropdown.ClearOptions(); List options = new(); HashSet added = new(); // évite les doublons foreach (var s in closest) { string label = $"{s.town}"; // ou s.name selon ton cas if (!added.Contains(label)) { added.Add(label); options.Add(new TMP_Dropdown.OptionData(label)); } } dropdown.AddOptions(options); if (options.Count > 0) dropdown.value = 0; dropdown.RefreshShownValue(); } private void ClearDropdown(string message) { if (dropdown == null) return; dropdown.ClearOptions(); dropdown.AddOptions(new List { new TMP_Dropdown.OptionData(message) }); dropdown.value = 0; dropdown.RefreshShownValue(); } private List ComputeStoreDistances(double userLat, double userLon) { List list = new(); // 🔹 Indices de colonnes (utilise ton système existant) int indLongitude = UIT.Ind(Library.Store, Header.Longitude); int indLatitude = UIT.Ind(Library.Store, Header.Latitude); int indName = UIT.Ind(Library.Store, Header.Store_Name); // adapte ce header si besoin int indTown = UIT.Ind(Library.Store, Header.Town); // 🔹 Chaque ligne de magasin dans ta librairie // Adapte le séparateur de lignes si nécessaire (\n ou autre) //string[] lines = _G.UIT_LibraryStores.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in _G.UIT_LibraryStores) { if(string.IsNullOrEmpty(line) && line!=_G.UIT_LibraryStores[0]){continue;} // Adapte le séparateur de colonnes si ce n'est pas une virgule. string[] cols = line.Split(','); if (cols.Length <= Math.Max(indLongitude, Math.Max(indLatitude, indName))) continue; string sLat = cols[indLatitude].Trim(); string sLon = cols[indLongitude].Trim(); string sName = cols[indName].Trim(); string stown= cols[indTown].Trim(); if (string.IsNullOrEmpty(sLat) || string.IsNullOrEmpty(sLon)) continue; if (!double.TryParse(sLat, NumberStyles.Float, CultureInfo.InvariantCulture, out double storeLat)) continue; if (!double.TryParse(sLon, NumberStyles.Float, CultureInfo.InvariantCulture, out double storeLon)) continue; double d = HaversineDistanceKm(userLat, userLon, storeLat, storeLon); list.Add(new StoreDistance { town = stown, name = sName, lineRaw = line, distanceKm = d }); } return list; } private double HaversineDistanceKm(double lat1, double lon1, double lat2, double lon2) { const double R = 6371.0; // rayon de la Terre en km double dLat = Deg2Rad(lat2 - lat1); double dLon = Deg2Rad(lon2 - lon1); double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Deg2Rad(lat1)) * Math.Cos(Deg2Rad(lat2)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); return R * c; } private double Deg2Rad(double deg) => deg * Math.PI / 180.0; }