예제 #1
0
        public async Task <PlanElementCandidate> GenerateAsync(DecisionArray decisionArray, Plan plan, int whichMeal, PlanElementIteratorParams iterParams)
        {
            var test = true;
            //choose type based on preferences
            var type                  = (plan.PlanForm.FoodPreference == FoodPreference.OnlyRestaurant || (plan.PlanForm.FoodPreference == FoodPreference.Mixed && whichMeal == 2)) ? GooglePlaceTypeCategory.Restaurant : GooglePlaceTypeCategory.Food;
            var candidates            = new List <PlanElementCandidate>();
            var decisionRows          = new List <DecisionRow>();
            var googleNearbyFoodInput = _googlePlaceNearbySearchInputFactory.Create(iterParams.CurrentLocation, type);
            var nearbyFoodResults     = await _googlePlaceNearbySearchApiClient.GetAsync(googleNearbyFoodInput);

            int counter = 1;

            foreach (var nr in nearbyFoodResults.results)
            {
                var details = await _googlePlaceDetailsApiClient.GetAsync(_googlePlaceDetailsInputFactory.CreateAllUseful(nr.place_id));

                if (details.IsOk)
                {
                    var candidate = new PlanElementCandidate(details.Result.name, details.Result.place_id, details.Result.formatted_address, details.Result.geometry.location, details.Result.opening_hours, details.Result.types, details.Result.rating, details.Result.price_level, details.Result.user_ratings_total);
                    if (test)
                    {
                        return(candidate);
                    }

                    candidates.Add(candidate);
                }
                ++counter;
                if (counter > 10 && candidates.Count > 5)
                {
                    break;
                }
            }



            var iter = 1;

            foreach (var candidate in candidates)
            {
                decisionRows.Add(_decisionRowFactory.Create(candidate, iter, iterParams.CurrentLocation));
                ++iter;
            }

            var minVector = DecisionArray.GetMinVector(decisionRows);
            var maxVector = DecisionArray.GetMaxVector(decisionRows);

            foreach (var decisionRow in decisionRows)
            {
                decisionRow.NormalizedScore = _sawMethod.CalculateNormalizedScore(SawNormalizationMethod.LinearFirstType, decisionArray.WeightVector, decisionRow.DecisionValues, minVector, maxVector);
            }

            var result = decisionRows.OrderByDescending(x => x.NormalizedScore).FirstOrDefault(x => x.Candidate.IsOpen(iterParams.CurrentDateTime));

            if (result == null)
            {
                throw new UserFriendlyException($"Nie udało się znaleźć żadnego miejsca, gdzie można zjeść w pobliżu o godz: {iterParams.CurrentDateTime}");
            }

            return(result.Candidate);
        }
예제 #2
0
        public async Task <Plan> GenerateAsync(PlanForm planForm)
        {
            // 1. Create decision array
            var DecisionArray = new DecisionArray();

            // 2. Create plan object. Validate desitnation and accomodation.
            var destinationInfo = await _googlePlaceDetailsApiClient.GetAsync(_googlePlaceDetailsInputFactory.CreateAllUseful(planForm.PlaceId));

            var plan = new Plan(destinationInfo.Result.name, destinationInfo.Result.geometry.location.lat, destinationInfo.Result.geometry.location.lng,
                                (decimal?)destinationInfo.Result.rating, (decimal?)destinationInfo.Result.user_ratings_total, destinationInfo.Result.formatted_address);

            if (planForm.HasAccomodationBooked)
            {
                var accomodationInfo = await _googlePlaceDetailsApiClient.GetAsync(_googlePlaceDetailsInputFactory.CreateAllUseful(planForm.AccomodationId));

                plan.PlanAccomodation = new PlanAccomodation(accomodationInfo.Result.geometry.location.lat, accomodationInfo.Result.geometry.location.lng, planForm.AccomodationId,
                                                             accomodationInfo.Result.name, accomodationInfo.Result.formatted_address, (decimal?)accomodationInfo.Result.rating, (decimal?)accomodationInfo.Result.user_ratings_total);

                var distance = CalculateDistance(plan.Latitude, plan.Longitude, plan.PlanAccomodation.Lat, plan.PlanAccomodation.Lng);

                if (distance > MaximumDistanceToAccomodation) //more than 15km
                {
                    throw new UserFriendlyException($"Odległość między celem podróży a miejscem zakwaterowania nie może być większa nić {(int)(MaximumDistanceToAccomodation/1000)} km");
                }
            }

            plan.PlanForm    = planForm;
            plan.Assumptions = new PlanAssumptions(planForm);

            // 3. Generate weight vector based on user preferences
            DecisionArray.WeightVector = _weightVectorProvider.Generate(planForm);
            plan.PlanFormWeightVector  = PlanFormWeightVector.Create(DecisionArray.WeightVector);

            // 4. Get plan candidates
            var candidates = await _planElementCandidateFactory.GetCandidates(plan, DecisionArray.WeightVector);

            //5. Create decision row with values based on candidates
            int init = 1;

            foreach (var candidate in candidates)
            {
                DecisionArray.DecisionRows.Add(_decisionRowFactory.Create(candidate, init, plan.StartLocation));
                ++init;
            }

            // 6. SCORE FUNCTION -> SAW Normalization (3 types - chosen first) and then calculate Score
            var minVector = DecisionArray.GetMinVector();
            var maxVector = DecisionArray.GetMaxVector();

            foreach (var decisionRow in DecisionArray.DecisionRows)
            {
                decisionRow.NormalizedScore = _sawMethod.CalculateNormalizedScore(SawNormalizationMethod.LinearFirstType, DecisionArray.WeightVector, decisionRow.DecisionValues, minVector, maxVector);
            }

            // 7. Clasification
            DecisionArray.DecisionRows = DecisionArray.DecisionRows.OrderByDescending(x => x.NormalizedScore).ToList();
            int newPos = 1;

            foreach (var row in DecisionArray.DecisionRows)
            {
                row.ScorePosition = newPos;
                ++newPos;
            }

            // 8. Create Plan based on decision rows and optimize routes with travel salesman problem
            plan.Elements = await _planElementsProvider.GenerateAsync(DecisionArray, plan);

            return(plan);
        }