/// <summary> /// Checks the not duplicate measured course. /// </summary> /// <param name="measuredCourse">The measured course.</param> /// <exception cref="InvalidOperationException">Unable to add measured course as this has a duplicate Course Id</exception> private void CheckNotDuplicateMeasuredCourse(MeasuredCourseDataTransferObject measuredCourse) { if (this.MeasuredCourses.Any(m => m.MeasuredCourseId == measuredCourse.MeasuredCourseId)) { throw new InvalidOperationException("Unable to add measured course as this has a duplicate Course Id"); } }
/// <summary> /// Gets the measured course. /// </summary> /// <param name="measuredCourseId">The measured course identifier.</param> /// <returns></returns> /// <exception cref="NotFoundException">No measured course found for Club {this.Name} with Measured Course Id {measuredCourseId}</exception> public MeasuredCourseDataTransferObject GetMeasuredCourse(Guid measuredCourseId) { Boolean measuredCourseFound = this.MeasuredCourses.Any(m => m.MeasuredCourseId == measuredCourseId); if (!measuredCourseFound) { throw new NotFoundException($"No measured course found for Club {this.Name} with Measured Course Id {measuredCourseId}"); } MeasuredCourse measuredCourse = this.MeasuredCourses.Where(m => m.MeasuredCourseId == measuredCourseId).Single(); MeasuredCourseDataTransferObject result = new MeasuredCourseDataTransferObject { Name = measuredCourse.Name, MeasuredCourseId = measuredCourse.MeasuredCourseId, StandardScratchScore = measuredCourse.StandardScratchScore, TeeColour = measuredCourse.TeeColour, Holes = new List <HoleDataTransferObject>() }; foreach (Hole measuredCourseHole in measuredCourse.Holes) { result.Holes.Add(new HoleDataTransferObject { HoleNumber = measuredCourseHole.HoleNumber, Par = measuredCourseHole.Par, LengthInYards = measuredCourseHole.LengthInYards, StrokeIndex = measuredCourseHole.StrokeIndex, LengthInMeters = measuredCourseHole.LengthInMeters }); } return(result); }
/// <summary> /// Validates the measured course. /// </summary> /// <param name="measuredCourse">The measured course.</param> private void ValidateMeasuredCourse(MeasuredCourseDataTransferObject measuredCourse) { Guard.ThrowIfInvalidGuid(measuredCourse.MeasuredCourseId, typeof(ArgumentNullException), "A measured course must have a valid Id"); Guard.ThrowIfNullOrEmpty(measuredCourse.Name, typeof(ArgumentNullException), "A measured course must have a name"); Guard.ThrowIfNullOrEmpty(measuredCourse.TeeColour, typeof(ArgumentNullException), "A measured course must have a tee colour"); Guard.ThrowIfNegative(measuredCourse.StandardScratchScore, typeof(ArgumentNullException), "A measured course must have a non negative Standard Scratch Score"); Guard.ThrowIfZero(measuredCourse.StandardScratchScore, typeof(ArgumentNullException), "A measured course must have a non zero Standard Scratch Score"); // Only validate the holes if the have been populated if (measuredCourse.Holes.Count != 18) { throw new InvalidDataException("A measured course must have 18 holes"); } // Check there are no missing hole numbers IEnumerable <Int32> holeNumberList = measuredCourse.Holes.Select(h => h.HoleNumber); List <Int32> missingHoleNumbers = Enumerable .Range(GolfClubAggregate.MinimumHoleNumber, GolfClubAggregate.MaximumHoleNumber - GolfClubAggregate.MinimumHoleNumber + 1) .Except(holeNumberList).ToList(); if (missingHoleNumbers.Count > 0) { // there are missing hole numbers throw new InvalidDataException($"Hole numbers {string.Join(",", missingHoleNumbers)} are missing from the measured course"); } // Check there are no missing stroke indexes IEnumerable <Int32> strokeIndexList = measuredCourse.Holes.Select(h => h.StrokeIndex); List <Int32> missingStrokeIndexes = Enumerable .Range(GolfClubAggregate.MinimumStrokeIndex, GolfClubAggregate.MaximumStrokeIndex - GolfClubAggregate.MinimumStrokeIndex + 1).Except(strokeIndexList).ToList(); if (missingStrokeIndexes.Count > 0) { // there are missing stroke indexes throw new InvalidDataException($"Hole with Stroke Indexes {string.Join(",", missingStrokeIndexes)} are missing from the measured course"); } // Check all holes have a valid length in yards IEnumerable <Int32> holesWithInvalidLengthInYards = measuredCourse.Holes.Where(h => h.LengthInYards <= 0).Select(h => h.HoleNumber); if (holesWithInvalidLengthInYards.Any()) { throw new InvalidDataException($"All holes must have a length in yards, hole numbers {string.Join(",", holesWithInvalidLengthInYards)} are missing a valid length in yards"); } // Check all holes have a valid par IEnumerable <Int32> holesWithInvalidPar = measuredCourse.Holes.Where(h => h.Par != 3 && h.Par != 4 && h.Par != 5).Select(h => h.HoleNumber); if (holesWithInvalidPar.Any()) { throw new InvalidDataException($"All holes must have a valid Par of 3,4 or 5, hole numbers {string.Join(",", holesWithInvalidPar)} are missing a valid Par"); } }
/// <summary> /// Gets the measured courses. /// </summary> /// <returns></returns> /// <exception cref="NotFoundException">No measured courses found for Club {this.Name}</exception> public List <MeasuredCourseDataTransferObject> GetMeasuredCourses() { if (this.MeasuredCourses.Any() == false) { throw new NotFoundException($"No measured courses found for Club {this.Name}"); } List <MeasuredCourseDataTransferObject> measuredCourses = new List <MeasuredCourseDataTransferObject>(); foreach (MeasuredCourse measuredCourse in this.MeasuredCourses) { MeasuredCourseDataTransferObject result = new MeasuredCourseDataTransferObject { Name = measuredCourse.Name, MeasuredCourseId = measuredCourse.MeasuredCourseId, StandardScratchScore = measuredCourse.StandardScratchScore, TeeColour = measuredCourse.TeeColour, Holes = new List <HoleDataTransferObject>() }; foreach (Hole measuredCourseHole in measuredCourse.Holes) { result.Holes.Add(new HoleDataTransferObject { HoleNumber = measuredCourseHole.HoleNumber, Par = measuredCourseHole.Par, LengthInYards = measuredCourseHole.LengthInYards, StrokeIndex = measuredCourseHole.StrokeIndex, LengthInMeters = measuredCourseHole.LengthInMeters }); } measuredCourses.Add(result); } return(measuredCourses); }
/// <summary> /// Adds the measured course. /// </summary> /// <param name="measuredCourse">The measured course.</param> public void AddMeasuredCourse(MeasuredCourseDataTransferObject measuredCourse) { // Apply the business rules here // Check club has been created this.CheckHasGolfClubAlreadyBeenCreated(); // Check for a duplicate measured course addition this.CheckNotDuplicateMeasuredCourse(measuredCourse); // Validate the measured course data this.ValidateMeasuredCourse(measuredCourse); // Now apply and pend the required events // First the measured course added event MeasuredCourseAddedEvent measuredCourseAddedEvent = MeasuredCourseAddedEvent.Create(this.AggregateId, measuredCourse.MeasuredCourseId, measuredCourse.Name, measuredCourse.TeeColour, measuredCourse.StandardScratchScore); this.ApplyAndPend(measuredCourseAddedEvent); // Now add an event for each hole foreach (HoleDataTransferObject holeDataTransferObject in measuredCourse.Holes) { HoleAddedToMeasuredCourseEvent holeAddedToMeasuredCourseEvent = HoleAddedToMeasuredCourseEvent.Create(this.AggregateId, measuredCourse.MeasuredCourseId, holeDataTransferObject.HoleNumber, holeDataTransferObject.LengthInYards, holeDataTransferObject.LengthInMeters, holeDataTransferObject.Par, holeDataTransferObject.StrokeIndex); this.ApplyAndPend(holeAddedToMeasuredCourseEvent); } }