Ejemplo n.º 1
0
        public ToyCalculator(string text)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ToyDistributionProblem));

            using (TextReader reader = new StringReader(text))
            {
                toyDistributionProblem = (ToyDistributionProblem)serializer.Deserialize(reader);
            }
        }
        public async Task <Uri> Save(Attempt attempt, ToyDistributionProblem problem, CancellationToken token)
        {
            if (attempt == null)
            {
                throw new ArgumentNullException(nameof(attempt));
            }
            if (problem == null)
            {
                throw new ArgumentNullException(nameof(problem));
            }

            CloudBlockBlob blob = Container.GetBlockBlobReference(FileName(attempt));

            using var stream    = new MemoryStream();
            using var xmlWriter = new XmlTextWriter(stream, Encoding.UTF8);

            Serializer.Serialize(xmlWriter, problem);

            stream.Seek(0, SeekOrigin.Begin);

            await blob.UploadFromStreamAsync(stream, token);

            return(blob.Uri);
        }
Ejemplo n.º 3
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
            ILogger logger,
            CancellationToken token)
        {
            return(await req.Wrap <ReindeerRescueRequest>(logger, async request =>
            {
                if (request == null)
                {
                    return new BadRequestErrorMessageResult("Request is empty.");
                }

                if (string.IsNullOrWhiteSpace(request.Id))
                {
                    return new BadRequestErrorMessageResult($"Missing required value for property '{nameof(ReindeerRescueRequest.Id)}'.");
                }

                if (!Guid.TryParse(request.Id, out Guid id))
                {
                    return new BadRequestErrorMessageResult($"Value for property '{nameof(ReindeerRescueRequest.Id)}' is not a valid ID or has an invalid format (example of valid value and format for Unique Identifier (GUID): '135996C9-3090-4399-85DB-1F5041DF1DDD').");
                }

                Attempt attempt = await _attemptService.Get(id, 2, token);

                if (attempt == null)
                {
                    return new NotFoundResult();
                }

                if (!attempt.SantaRescueAt.HasValue)
                {
                    return new BadRequestErrorMessageResult($"It looks like you're reusing an old ID from a previous failed attempt created {attempt.Created} - you need to start all over again - remember not to hard code any IDs in your application.");
                }

                if (attempt.ReindeerInZones == null)
                {
                    throw new InvalidOperationException($"Missing value for '{nameof(attempt.ReindeerInZones)}' on attempt with Id '{attempt.Id}'.");
                }

                var messages = new List <string>();

                if (request.Locations == null)
                {
                    messages.Add($"Missing required value for property '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}'.");
                }
                else if (request.Locations.Length > attempt.ReindeerInZones.Length)
                {
                    messages.Add($"Invalid value for property '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}'. Expected a maximum number of locations to be {attempt.ReindeerInZones.Length} - but was {request.Locations.Length}.");
                }
                else
                {
                    for (int i = 0; i < attempt.ReindeerInZones.Length; i++)
                    {
                        ReindeerInZone zone = attempt.ReindeerInZones[i];
                        ReindeerRescueRequest.ReindeerLocation locationInRequest = request.Locations?.ElementAtOrDefault(i);

                        if (locationInRequest == null)
                        {
                            messages.Add($"Missing required value for property '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}[{i}]'.");
                        }
                        else if (string.IsNullOrWhiteSpace(locationInRequest.Name))
                        {
                            messages.Add($"Missing required value for property '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}[{i}].{nameof(ReindeerRescueRequest.ReindeerLocation.Name).WithFirstCharToLowercase()}'");
                        }
                        else if (locationInRequest.Name.Length >= 100)
                        {
                            messages.Add($"Invalid value for property '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}[{i}].{nameof(ReindeerRescueRequest.ReindeerLocation.Name).WithFirstCharToLowercase()}' - length exceeds maximum of 100 characters.");
                        }
                        else if (!string.Equals(locationInRequest.Name, zone.Reindeer.ToString()))
                        {
                            messages.Add($"Expected name of Reindeer for '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}[{i}].{nameof(ReindeerRescueRequest.ReindeerLocation.Name).WithFirstCharToLowercase()}' to be '{zone.Reindeer}' - but was '{locationInRequest.Name}'.");
                        }
                        else if (locationInRequest.Position == null)
                        {
                            messages.Add($"Missing required value for property '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}[{i}].{nameof(ReindeerRescueRequest.ReindeerLocation.Position).WithFirstCharToLowercase()}'");
                        }
                        else
                        {
                            Point center = new Point(zone.Center.Lon, zone.Center.Lat);
                            double radiusInMeter = zone.Radius.InMeter();
                            string name = zone.Reindeer.ToString();

                            var feedOptions = new FeedOptions
                            {
                                PartitionKey = new PartitionKey(zone.CountryCode),
                                MaxItemCount = 1
                            };

                            ObjectInLocationForCosmosDb actualReindeer = _documentClient
                                                                         .CreateDocumentQuery <ObjectInLocationForCosmosDb>(UriFactory.CreateDocumentCollectionUri("World", "Objects"), feedOptions)
                                                                         .Where(u => u.Name == name && center.Distance(u.Location) <= radiusInMeter)
                                                                         .AsEnumerable()
                                                                         .FirstOrDefault();

                            if (actualReindeer == null)
                            {
                                throw new InvalidOperationException($"Reindeer '{name}' not found for zone {zone.Center}, Country {zone.CountryCode}.");
                            }

                            GeoPoint actualPosition = actualReindeer.GetLocation();

                            if (!actualPosition.Equals(locationInRequest.Position))
                            {
                                messages.Add($"Invalid value for property '{nameof(ReindeerRescueRequest.Locations).WithFirstCharToLowercase()}[{i}].{nameof(ReindeerRescueRequest.ReindeerLocation.Position).WithFirstCharToLowercase()}'. Reindeer '{zone.Reindeer}' was not found at {locationInRequest.Position} - actual position is {actualPosition}.");
                            }
                        }
                    }
                }

                if (messages.Count > 0)
                {
                    attempt.InvalidReindeerRescue = messages.ToArray();

                    await _attemptService.Save(attempt, 3, token);

                    return new BadRequestErrorMessageResult($@"Unfortunately one or more reindeer was not at the specified locations. 
Below is the detailed rescue report from the extraction team:

{string.Join(Environment.NewLine, messages.Select(x => $"\t - {x}"))}

Please try again - and remember since the reindeer has probably moved their locations by now, you'll have to start all over again.");
                }

                attempt.ReindeersRescueAt = DateTimeOffset.UtcNow;

                Uri problemUri = await _toyDistributionProblemRepository.Save(attempt, ToyDistributionProblem.Create(), token);

                await _attemptService.Save(attempt, 3, token);

                return new OkObjectResult(new ReindeerRescueResponse(problemUri));
            }));
        }
Ejemplo n.º 4
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger logger,
            CancellationToken token)
        {
            return(await req.Wrap <ToyDistributionRequest>(logger, async request =>
            {
                if (request == null)
                {
                    return new BadRequestErrorMessageResult("Request is empty.");
                }

                if (string.IsNullOrWhiteSpace(request.Id))
                {
                    return new BadRequestErrorMessageResult($"Missing required value for property '{nameof(SantaRescueRequest.Id)}'.");
                }

                if (!Guid.TryParse(request.Id, out Guid id))
                {
                    return new BadRequestErrorMessageResult($"Value for property '{nameof(SantaRescueRequest.Id)}' is not a valid ID or has an invalid format (example of valid value and format for Unique Identifier (GUID): '135996C9-3090-4399-85DB-1F5041DF1DDD').");
                }

                Attempt attempt = await _attemptService.Get(id, 3, token);

                if (attempt == null)
                {
                    return new NotFoundResult();
                }

                if (!attempt.ReindeersRescueAt.HasValue)
                {
                    return new BadRequestErrorMessageResult($"It looks like you're reusing an old ID from a previous failed attempt created {attempt.Created} - you need to start all over again - remember not to hard code any IDs in your application.");
                }

                var messages = new List <string>();

                if (request.ToyDistribution == null)
                {
                    messages.Add($"Missing required value for property '{nameof(ToyDistributionRequest.ToyDistribution).WithFirstCharToLowercase()}'.");
                }
                else if (request.ToyDistribution.Length != ToyDistributionProblem.ListLength)
                {
                    messages.Add($"Invalid value for property '{nameof(ToyDistributionRequest.ToyDistribution).WithFirstCharToLowercase()}'. Expected number of elements to be {ToyDistributionProblem.ListLength} - but was {request.ToyDistribution.Length}.");
                }
                else
                {
                    for (int i = 0; i < request.ToyDistribution.Length; i++)
                    {
                        ToyDistributionRequest.ChildGettingToy pair = request.ToyDistribution[i];

                        if (pair == null)
                        {
                            messages.Add($"Missing required value for property '{nameof(ToyDistributionRequest.ToyDistribution).WithFirstCharToLowercase()}[{i}]'.");
                        }
                        else if (string.IsNullOrWhiteSpace(pair.ChildName))
                        {
                            messages.Add($"Missing required value for property '{nameof(ToyDistributionRequest.ToyDistribution).WithFirstCharToLowercase()}[{i}].{nameof(ToyDistributionRequest.ChildGettingToy.ChildName).WithFirstCharToLowercase()}'");
                        }
                        else if (pair.ChildName.Length >= 100)
                        {
                            messages.Add($"Invalid value for property '{nameof(ToyDistributionRequest.ToyDistribution).WithFirstCharToLowercase()}[{i}].{nameof(ToyDistributionRequest.ChildGettingToy.ChildName).WithFirstCharToLowercase()}' - length exceeds maximum of 100 characters.");
                        }
                        else if (string.IsNullOrWhiteSpace(pair.ToyName))
                        {
                            messages.Add($"Missing required value for property '{nameof(ToyDistributionRequest.ToyDistribution).WithFirstCharToLowercase()}[{i}].{nameof(ToyDistributionRequest.ChildGettingToy.ToyName).WithFirstCharToLowercase()}'");
                        }
                        else if (pair.ToyName.Length >= 100)
                        {
                            messages.Add($"Invalid value for property '{nameof(ToyDistributionRequest.ToyDistribution).WithFirstCharToLowercase()}[{i}].{nameof(ToyDistributionRequest.ChildGettingToy.ToyName).WithFirstCharToLowercase()}' - length exceeds maximum of 100 characters.");
                        }
                    }

                    string[] duplicateChildNames = request.ToyDistribution
                                                   .Where(x => !string.IsNullOrWhiteSpace(x?.ChildName))
                                                   .GroupBy(x => x.ChildName, StringComparer.OrdinalIgnoreCase)
                                                   .Where(x => x.Count() > 1)
                                                   .Select(x => x.Key)
                                                   .ToArray();

                    if (duplicateChildNames.Length > 0)
                    {
                        messages.Add($"You have the same child name mentioned more than once in the request. This is not allowed. Duplicate name(s): {string.Join(", ", duplicateChildNames)}");
                    }

                    string[] duplicateToyNames = request.ToyDistribution
                                                 .Where(x => !string.IsNullOrWhiteSpace(x?.ToyName))
                                                 .GroupBy(x => x.ToyName, StringComparer.OrdinalIgnoreCase)
                                                 .Where(x => x.Count() > 1)
                                                 .Select(x => x.Key)
                                                 .ToArray();

                    if (duplicateToyNames.Length > 0)
                    {
                        messages.Add($"You have the same toy name mentioned more than once in the request. This is not allowed. Duplicate name(s): {string.Join(", ", duplicateToyNames)}");
                    }
                }

                if (messages.Count == 0)
                {
                    ToyDistributionProblem problem = await _toyDistributionProblemRepository.Get(attempt, token);

                    if (problem == null)
                    {
                        throw new InvalidOperationException($"No problem found for {attempt.Id}.");
                    }

                    string[] missingChildren = problem.Children
                                               .Select(x => x.Name)
                                               .Except(request.ToyDistribution?.Select(x => x.ChildName) ?? new string[0])
                                               .ToArray();

                    if (missingChildren.Length > 0)
                    {
                        messages.Add($@"One or more children names are missing from your list: 
 - Expected: {string.Join(", ", problem.Children.Select(x => x.Name))}
 - Actual: {string.Join(", ", request.ToyDistribution?.Select(x => x.ChildName) ?? new string[0])}");
                    }
                    else
                    {
                        var proposedSolution = new ToyDistributionSolution
                        {
                            List = request.ToyDistribution?.ToDictionary(x => x.ChildName, x => x.ToyName)
                        };

                        if (!proposedSolution.IsValidFor(problem))
                        {
                            ToyDistributionSolution validSolution = problem.CreateSolution();

                            messages.Add($@"The proposed solution was not found correct. Below is a correct solution to the problem:
{string.Join(Environment.NewLine, validSolution.List.Select(x => $"\t\t- '{x.Key}' gets '{x.Value}'"))}");
                        }
                    }
                }

                if (messages.Count > 0)
                {
                    attempt.InvalidSolution = request.ToyDistribution?
                                              .Take(ToyDistributionProblem.ListLength * 2)
                                              .Select(x => new KeyValuePair <string, string>(
                                                          x?.ChildName.MaxLengthWithDots(100),
                                                          x?.ToyName.MaxLengthWithDots(100)))
                                              .ToArray();

                    await _attemptService.Save(attempt, 4, token);

                    return new BadRequestErrorMessageResult($@"Unfortunately you have one or more errors:

{string.Join(Environment.NewLine, messages.Select(x => $"\t - {x}"))}

Please try again - and remember, as always, you'll have to start all over again.");
                }

                attempt.CompletedAt = DateTimeOffset.UtcNow;

                await _attemptService.Save(attempt, 4, token);

                return new OkObjectResult(new ToyDistributionResponse(await _attemptService.GetStatistics(attempt, token)));
            }));
        }
Ejemplo n.º 5
0
        private static async Task Låge4(ParticipateResponse participateResponse, string xmlUrl, HttpClient httpClient)
        {
            Console.WriteLine("Parsing XML...");

            XDocument xmlDocument = XDocument.Load(xmlUrl);

            ToyDistributionProblem parsedXml = XmlSerializerUtil.Deserialize <ToyDistributionProblem>(xmlDocument);

            Console.WriteLine($"Xml parsed to object...{parsedXml.Children.Count} children and {parsedXml.Toys.Count} toys...");

            Console.WriteLine("Starting to distribute toys to children...");

            Queue <Child> remainingChilren = new Queue <Child>(parsedXml.Children);

            int counter = 0;
            ToyDistributorHelper toyDistributor = new ToyDistributorHelper(parsedXml.Toys);
            //ToyDistributionResult result = new ToyDistributionResult();
            List <ToyDistribution> distributionResult = new List <ToyDistribution>();

            try
            {
                while (remainingChilren.Count > 0)
                {
                    Console.WriteLine($"Iteration: {counter}");

                    Child currentChild = remainingChilren.Dequeue();

                    Toy  foundToy;
                    bool resolved = toyDistributor.TryResolve(currentChild, out foundToy);

                    if (resolved)
                    {
                        distributionResult.Add(new ToyDistribution()
                        {
                            ChildName = currentChild.Name, ToyName = foundToy.Name
                        });
                        toyDistributor.RemoveToy(foundToy);
                    }
                    else
                    {
                        remainingChilren.Enqueue(currentChild);
                    }

                    counter++;

                    if (counter > 50)
                    {
                        break;
                    }
                }

                //Console.WriteLine($"Toy distribution result: {result.ToString()}");

                //List<ToyDistribution> distributionResult = new List<ToyDistribution>();
                //foreach (var res in result.ToyDistribution)
                //{
                //    distributionResult.Add(new ToyDistribution() { ChildName = res.Key, ToyName = res.Value });
                //}

                HttpResponseMessage toyDistributionResponse = await httpClient.PostAsJsonAsync("/api/toydistribution", new { id = participateResponse.Id, toyDistribution = distributionResult });

                if (!toyDistributionResponse.IsSuccessStatusCode)
                {
                    string reason = await toyDistributionResponse.Content.ReadAsStringAsync();

                    throw new ChristmasException($"{toyDistributionResponse.StatusCode}: {(await toyDistributionResponse.Content.ReadAsStringAsync())}");
                }

                Console.WriteLine("##############################################################################");

                string apiResult = await toyDistributionResponse.Content.ReadAsStringAsync();

                Console.WriteLine(apiResult);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
        }