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); }
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)); })); }
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))); })); }
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); } }