public static (TourModel, List <List <PlaceEntity> >) Sort(TourDetailsEntity tourDetails, TourModel tour, WeatherEntity weather) { tour.RemoveNulls(); int maxDistance; int maxTime; double transportModifier; using (StreamReader r = new StreamReader("F:/SmartTour/Front-End/smart-tour/src/assets/subtypeConfig.json")) { string json = r.ReadToEnd(); SubtypeDataEntity subtypeData = JsonConvert.DeserializeObject <SubtypeDataEntity>(json); switch (tourDetails.DistanceRange) { case "less than 5 km": maxDistance = 5; break; case "less than 10 km": maxDistance = 10; break; case "less than 20 km": maxDistance = 20; break; default: maxDistance = 30; break; } switch (tourDetails.Transport) { case "by personal car": transportModifier = 1.5; break; case "by bycicle": transportModifier = 0.9; break; case "by foot": transportModifier = 0.6; break; default: transportModifier = 1; break; } foreach (PlaceEntity place in tour.Tour) { double distance = GetDistance( double.Parse(tourDetails.Latitude, System.Globalization.CultureInfo.InvariantCulture), double.Parse(tourDetails.Longitude, System.Globalization.CultureInfo.InvariantCulture), double.Parse(place.Latitude, System.Globalization.CultureInfo.InvariantCulture), double.Parse(place.Longitude, System.Globalization.CultureInfo.InvariantCulture)); if (distance > maxDistance) { tour.Remove(place); } } switch (tourDetails.TimeRange) { case "less than 2 hours": maxTime = 2 * 60; break; case "less than 5 hours": maxTime = 5 * 60; break; case "less than 8 hours": maxTime = 8 * 60; break; default: maxTime = 12 * 60; break; } int[] timeList = new int[tour.Tour.Count()]; double[] ratingList = new double[tour.Tour.Count()]; foreach (PlaceEntity place in tour.Tour) { if (place.Rating == null) { place.Rating = "3.0"; } } double ratingMean = tour.Tour.Sum(item => double.Parse(item.Rating, System.Globalization.CultureInfo.InvariantCulture)) / tour.Tour.Count(); int t = 0; foreach (PlaceEntity place in tour.Tour) { if (place is AttractionEntity) { if (subtypeData.time.ContainsKey(((AttractionEntity)place).Subtype[0]["name"])) { timeList[t] = subtypeData.time[((AttractionEntity)place).Subtype[0]["name"]]; } else { timeList[t] = subtypeData.time["default"]; } ratingList[t] = 1 + (ratingMean - double.Parse(place.Rating, System.Globalization.CultureInfo.InvariantCulture)) / 2.5; t += 1; } } TourModel aux = tour.GetNRandomPlaces(maxTime, timeList, weather, subtypeData, tourDetails.EatingBreak, tourDetails.savedPlaces); // from the list returned by the TripAdvisor API, enough places to fill the time selected by the user will be selected randomly, with some elements // having a better probability to be chosen (depends on rating, distance from start, recommended time to visit the place) TourModel backup = new TourModel(tour.Tour); tour = aux; (double, double)[] coordList = new (double, double)[tour.Tour.Count() + 1];