public void ActivityScheduleGrid_ValidSchedule_OnlyActivityDefinitionBlocks()
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                string scheduleId = "MySchedule";
                _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }

            // Act - load the grid component
            RenderedComponent <ActivityScheduleGrid> component =
                _host.AddComponent <ActivityScheduleGrid>();

            // Assert
            List <HtmlNode> gridCells = component.FindAll("td")
                                        .Where(node => node.Attributes.AttributesWithName("data-name")
                                               .Any(a => a.Value.Equals("ActivityDefinition.Name"))).ToList();

            Assert.That(gridCells, Has.Count.EqualTo(activityDefinitions.Count * 4),
                        "Number of activity rows");
            List <string> cellActivityNames = gridCells.Select(c =>
                                                               c.InnerText).Distinct().ToList();

            Assert.That(cellActivityNames, Is.EquivalentTo(activityDefinitions.Select(ad => ad.Name)),
                        "Activity row names");
        }
        public void ActivityScheduleGrid_ValidSchedule_NoCapacityErrorStyles()
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                string scheduleId = "MySchedule";
                _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }

            // Act - load the grid component
            RenderedComponent <ActivityScheduleGrid> component =
                _host.AddComponent <ActivityScheduleGrid>();

            // Assert - none are marked over-subscribed or under-subscribed
            List <HtmlNode> countNodes = component.FindAll("td")
                                         .Where(node => node.Attributes.AttributesWithName("data-name")
                                                .Any(a => a.Value.Equals("AssignedCampers.Count"))).ToList();
            List <string> countClass = countNodes
                                       .Select(node => node.Attributes["class"].Value)
                                       .ToList();

            Assert.That(countClass, Has.None.Contains("capacity-over"),
                        "Activity block styles");
            Assert.That(countClass, Has.None.Contains("capacity-under"),
                        "Activity block styles");
        }
Exemple #3
0
        public async Task CamperScheduleGrid_SelectCamper_CamperActivitiesHilite()
        {
            // Arrange - run schedule with successful data set and load grid
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <ActivityDefinition> schedule;
            string scheduleId = "MySchedule";

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                schedule = _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }
            RenderedComponent <CamperScheduleGrid> component =
                _host.AddComponent <CamperScheduleGrid>();

            // Act - select a camper
            Camper selectedCamper = schedule.First().ScheduledBlocks.First()
                                    .AssignedCampers.First();
            HtmlNode nameCell = component.FindAll("button")
                                .First(node => node.InnerText.Equals(selectedCamper.FullName));
            await nameCell.ClickAsync();

            // Assert - load all the activity cells
            List <HtmlNode> activityCells = component.FindAll("select")
                                            .Where(node => node.Id.Contains('-')).ToList();
            // Only Activity cells with an activity matching the selected camper in that slot
            // should have the selected-camper-activity
            List <HtmlNode> selectedActivityCells = activityCells.Where(node =>
                                                                        node.Attributes.AttributesWithName("class")
                                                                        .Any(a => a.Value.Contains("selected-camper-activity"))).ToList();
            Dictionary <int, string> selectedCamperActivities = selectedCamper.ScheduledBlocks
                                                                .ToDictionary(b => b.TimeSlot, b => b.ActivityDefinition.Name);

            foreach (HtmlNode selectedActivityCell in selectedActivityCells)
            {
                int slotId = int.Parse(selectedActivityCell.Id.Split('-')[1]);
                Assert.That(selectedActivityCell.Attributes["value"].Value,
                            Is.EqualTo(selectedCamperActivities[slotId]),
                            $"{selectedActivityCell.Id}");
            }

            List <HtmlNode> unselectedActivityCells = activityCells.Where(node =>
                                                                          node.Attributes.AttributesWithName("class")
                                                                          .All(a => !a.Value.Contains("selected-camper-activity"))).ToList();

            foreach (HtmlNode unselectedActivityCell in unselectedActivityCells)
            {
                int slotId = int.Parse(unselectedActivityCell.Id.Split('-')[1]);
                Assert.That(unselectedActivityCell.Attributes["value"].Value,
                            Is.Not.EqualTo(selectedCamperActivities[slotId]),
                            $"{unselectedActivityCell.Id}");
            }
        }
Exemple #4
0
        public void CamperScheduleGrid_OverSubscribedSchedule_HasUnscheduledBlocks(int numberOfActivitiesToVerify)
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <ActivityDefinition> schedule;

            using (MemoryStream camperRequestStream = new MemoryStream(_overSubscribedCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                string scheduleId = "MySchedule";
                schedule = _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }

            // Act - load the grid component
            RenderedComponent <CamperScheduleGrid> component =
                _host.AddComponent <CamperScheduleGrid>();

            // Assert
            List <HtmlNode> nameCells = component.FindAll("td")
                                        .Where(node => node.Attributes.AttributesWithName("data-name")
                                               .Any(a => a.Value.Equals("FullName"))).ToList();
            int numberOfCampers = 104;

            Assert.That(nameCells, Has.Count.EqualTo(numberOfCampers),
                        "Number of camper rows");

            ActivityDefinition unscheduledActivity = schedule.First(ad =>
                                                                    ad.Name.Equals(SchedulerService.UnscheduledActivityName));

            foreach (var activity in schedule.Take(numberOfActivitiesToVerify).Append(unscheduledActivity))
            {
                for (int timeSlot = 0; timeSlot < ActivityBlock.MaximumTimeSlots; timeSlot++)
                {
                    IActivityBlock activityBlock = activity.ScheduledBlocks.First(
                        ab => ab.TimeSlot == timeSlot);
                    foreach (var camper in activityBlock.AssignedCampers)
                    {
                        string          camperSlotId    = $"{camper.FullName}-{timeSlot}";
                        List <HtmlNode> camperSlotCells = component.FindAll("select")
                                                          .Where(node => node.Attributes.AttributesWithName("id")
                                                                 .Any(a => a.Value.Equals(camperSlotId))).ToList();
                        Assert.That(camperSlotCells, Has.Count.EqualTo(1),
                                    $"Number of camper slots for Id = {camperSlotId}");
                        List <HtmlAttribute> valueAttributes = camperSlotCells[0].Attributes
                                                               .AttributesWithName("value").ToList();
                        Assert.That(valueAttributes, Has.Count.EqualTo(1),
                                    $"Number of value attributes on selector for ID={camperSlotId}");
                        Assert.That(valueAttributes[0].Value,
                                    Is.EqualTo(activity.Name), "Selected activity");
                    }
                }
            }
        }
Exemple #5
0
        public void ReadCamperRequests_UnknownActivity_returnsNull()
        {
            // Act
            List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(GoodFileLocation,
                                                                                     ActivityDefinitionTests.IncompleteActivityDefinitions, _logger);

            // Assert
            Assert.That(camperRequests, Is.Null, "Return from ReadCamperRequests");
        }
Exemple #6
0
        public void ReadCamperRequests_invalidRequestFile_returnsNull()
        {
            // Act
            List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(BadContentFileLocation,
                                                                                     ActivityDefinitionTests.DefaultActivityDefinitions, _logger);

            // Assert
            Assert.That(camperRequests, Is.Null, "Return from ReadCamperRequests");
        }
        public async Task ActivityScheduleGrid_SelectCamperActivity_AllActivitiesForCamperGroupHilited()
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <CamperRequests> camperRequests;
            string scheduleId = "MySchedule";

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }
            // Find a camper in a camper group
            List <HashSet <Camper> > camperGroups        = _schedulerService.GetCamperGroupsForScheduleId(scheduleId);
            HashSet <Camper>         selectedCamperGroup = camperGroups.First();
            // Pick a camper with a full name in the group
            Camper selectedCamper = selectedCamperGroup.First(c => !string.IsNullOrEmpty(c.FirstName));

            RenderedComponent <ActivityScheduleGrid> component =
                _host.AddComponent <ActivityScheduleGrid>();
            List <HtmlNode> camperActivityCells = component.FindAll("td")
                                                  .Where(node => node.Attributes.AttributesWithName("title")
                                                         .Any(a => a.Value.Equals(selectedCamper.FullName))).ToList();

            Assert.That(camperActivityCells, Has.Count.EqualTo(4),
                        "Number of camper activity cells");

            // Act - Click on the block 0 for the next activity
            HtmlNode clickTarget = camperActivityCells.First();
            await clickTarget.ClickAsync();

            // Assert - schedule has camper selected
            Assert.That(component.Instance.SelectedCamperGroup,
                        Is.EqualTo(selectedCamperGroup),
                        "Selected Camper Group");

            // Verify that all activity cells for the camper group are selected
            List <HtmlNode> selectedCamperGroupActivityCells = component.FindAll("td")
                                                               .Where(node => node.Attributes.AttributesWithName("class")
                                                                      .Any(a => a.Value.Contains("selected-camper-group"))).ToList();

            // The selected camper does not get selected-camper-group, only his peers
            Assert.That(selectedCamperGroupActivityCells, Has.Count.EqualTo(4 * (selectedCamperGroup.Count - 1)),
                        "Selected activity cells");
            // Check that each peer has 4 cells in the selected group set.
            foreach (Camper camper in selectedCamperGroup.Where(c => c != selectedCamper))
            {
                Assert.That(selectedCamperGroupActivityCells.Count(c =>
                                                                   c.Attributes["title"].Value.Split(',')[0].Equals(camper.LastName)),
                            Is.EqualTo(4), $"Activities for camper {camper.FullName}");
            }
        }
Exemple #8
0
        public void ReadCamperRequests_validInput_loadsList()
        {
            // Act
            List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(GoodFileLocation,
                                                                                     ActivityDefinitionTests.DefaultActivityDefinitions, _logger);

            // Assert
            Assert.That(camperRequests, Is.Not.Null, "Return from ReadCamperRequests");
            Assert.That(camperRequests.Count, Is.EqualTo(98), "Number of camper requests");
        }
Exemple #9
0
        public async Task CamperScheduleGrid_SelectCamper_CamperGroupRowsHilite()
        {
            // Arrange - run schedule with successful data set and load grid
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <ActivityDefinition> schedule;
            string scheduleId = "MySchedule";

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                schedule = _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }
            RenderedComponent <CamperScheduleGrid> component =
                _host.AddComponent <CamperScheduleGrid>();

            // Act - select a camper
            // Find a camper in a camper group
            List <HashSet <Camper> > camperGroups        = _schedulerService.GetCamperGroupsForScheduleId(scheduleId);
            HashSet <Camper>         selectedCamperGroup = camperGroups.First();
            // Pick a camper with a full name in the group
            Camper   selectedCamper = selectedCamperGroup.First(c => !string.IsNullOrEmpty(c.FirstName));
            HtmlNode nameCell       = component.FindAll("button")
                                      .First(node => node.InnerText.Equals(selectedCamper.FullName));
            await nameCell.ClickAsync();

            // Assert - load the row and verify it has the selected-camper-group class
            List <HtmlNode> selectedCamperGroupRows = component.FindAll("tr")
                                                      .Where(node => node.Attributes.AttributesWithName("class")
                                                             .Any(a => a.Value.Contains("selected-camper-group"))).ToList();

            // The selected camper does not get selected-camper-group, only his peers
            Assert.That(selectedCamperGroupRows, Has.Count.EqualTo(selectedCamperGroup.Count - 1),
                        "Selected camper group rows");
            // Check that each peer has a row in the set. Need to strip it down to the last names
            // because the group has incomplete names
            List <string> selectedCamperGroupLastNames = selectedCamperGroupRows.Select(g =>
                                                                                        g.Elements("td").First(n => n.Attributes.Any(a =>
                                                                                                                                     a.Name.Equals("data-name") && a.Value.Equals("FullName")))
                                                                                        .InnerText.Split(',')[0]).ToList();

            foreach (Camper camper in selectedCamperGroup.Where(c => c != selectedCamper))
            {
                Assert.That(selectedCamperGroupLastNames,
                            Has.One.EqualTo(camper.LastName), "Camper row name");
            }
        }
Exemple #10
0
        public void CamperScheduleGrid_ChangeCamperActivity_ScheduleIsUpdated(int camperIndex, int timeSlot)
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <ActivityDefinition> schedule;
            string scheduleId = "MySchedule";

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                schedule = _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }

            // Act - load the grid component and update a camper
            RenderedComponent <CamperScheduleGrid> component =
                _host.AddComponent <CamperScheduleGrid>();
            List <string> fullNames = component.FindAll("td")
                                      .Where(node => node.Attributes.AttributesWithName("data-name")
                                             .Any(a => a.Value.Equals("FullName")))
                                      .Select(node => node.InnerText).ToList();
            string          camperSlotId    = $"{fullNames[camperIndex]}-{timeSlot}";
            List <HtmlNode> camperSlotCells = component.FindAll("select")
                                              .Where(node => node.Attributes.AttributesWithName("id")
                                                     .Any(a => a.Value.Equals(camperSlotId))).ToList();
            List <HtmlAttribute> valueAttributes = camperSlotCells[0].Attributes
                                                   .AttributesWithName("value").ToList();
            string originalActivityName = valueAttributes[0].Value;
            string updatedActivityName  = schedule[0].Name == originalActivityName
                                ? schedule[1].Name : schedule[0].Name;

            camperSlotCells[0].Change(updatedActivityName);

            // Assert
            // Reload the schedule and verify the camper has changed the activity.
            List <ActivityDefinition> updatedSchedule = _schedulerService.GetSchedule(scheduleId);

            Assert.That(updatedSchedule.First(ad => ad.Name.Equals(originalActivityName))
                        .ScheduledBlocks[timeSlot].AssignedCampers.Select(c => c.FullName),
                        Has.None.EqualTo(fullNames[camperIndex]), "Source activity camper list");
            Assert.That(updatedSchedule.First(ad => ad.Name.Equals(updatedActivityName))
                        .ScheduledBlocks[timeSlot].AssignedCampers.Select(c => c.FullName),
                        Has.One.EqualTo(fullNames[camperIndex]), "Target activity camper list");
        }
        /// <summary>
        /// Generate a schedule from the built-in test data for camper requests.
        /// </summary>
        /// <returns>A successful schedule from the built-in test data</returns>
        private (List <ActivityDefinition> activityDefinitions, List <HashSet <Camper> > camperGroups) GenerateSchedule()
        {
            Assembly assembly = typeof(SchedulerServiceTests).Assembly;

            using (Stream camperRequestFile = assembly.GetManifestResourceStream(
                       "ActivitySchedulerFrontEnd.Tests.CamperRequests.csv"))
            {
                List <ActivityDefinition> activityDefinitions = _activityDefinitionService.GetActivityDefinition(
                    DefaultActivitySetName).ToList();
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(camperRequestFile,
                                                                                         activityDefinitions);
                Scheduler.ScheduleActivities(camperRequests, false, _logger);
                List <HashSet <Camper> > camperGroups = CamperRequests.GenerateCamperMateGroups(camperRequests);
                // Activity definitions now has the schedule
                return(activityDefinitions, camperGroups);
            }
        }
        public async Task ActivityScheduleGrid_SelectCamperActivity_AllActivitiesForCamperHilited()
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <CamperRequests> camperRequests;
            string scheduleId = "MySchedule";

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }
            RenderedComponent <ActivityScheduleGrid> component =
                _host.AddComponent <ActivityScheduleGrid>();
            List <HtmlNode> camperActivityCells = component.FindAll("td")
                                                  .Where(node => node.Attributes.AttributesWithName("class")
                                                         .Any(a => a.Value.Contains("activity-camper-cell"))).ToList();

            Assert.That(camperActivityCells, Has.Count.EqualTo(camperRequests.Count() * 4),
                        "Number of camper activity cells");

            // Act - Click on the block 0 for the next activity
            HtmlNode clickTarget = camperActivityCells.First();
            await clickTarget.ClickAsync();

            // Assert - schedule has camper selected
            Assert.That(component.Instance.SelectedCamper?.FullName,
                        Is.EqualTo(clickTarget.Attributes["title"].Value),
                        "Selected Camper Name");

            // Verify that all activity cells for the camper are selected
            List <HtmlNode> selectedCamperActivityCells = component.FindAll("td")
                                                          .Where(node => node.Attributes.AttributesWithName("class")
                                                                 .Any(a => a.Value.Contains("selected-camper"))).ToList();

            Assert.That(selectedCamperActivityCells, Has.Count.EqualTo(4),
                        "Selected activity cells");
            Assert.That(selectedCamperActivityCells.Select(c => c.Attributes["title"].Value),
                        Has.All.EqualTo(component.Instance.SelectedCamper?.FullName),
                        "Selected cell camper names");
        }
        public void ActivityScheduleGrid_OverSubscribedSchedule_HasUnscheduledBlocks()
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));

            using (MemoryStream camperRequestStream = new MemoryStream(_overSubscribedCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                string scheduleId = "MySchedule";
                _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }

            // Act - load the grid component
            RenderedComponent <ActivityScheduleGrid> component =
                _host.AddComponent <ActivityScheduleGrid>();

            // Assert - activity definition has a new activity for unscheduled
            List <string> originalActivityNames = _activityDefinitionService.GetActivityDefinition(DefaultSetName)
                                                  .Select(ad => ad.Name).ToList();
            List <string> addedActivityNames = activityDefinitions.Select(ad => ad.Name)
                                               .Except(originalActivityNames).ToList();

            Assert.That(addedActivityNames, Has.Count.EqualTo(1),
                        "Number of activity definitions added by scheduling");
            Assert.That(addedActivityNames[0], Is.EqualTo(SchedulerService.UnscheduledActivityName),
                        "Name of activity added by scheduling");

            // Check that all of the activities included the added 1 are on the grid
            List <HtmlNode> gridCells = component.FindAll("td")
                                        .Where(node => node.Attributes.AttributesWithName("data-name")
                                               .Any(a => a.Value.Equals("ActivityDefinition.Name"))).ToList();

            Assert.That(gridCells, Has.Count.EqualTo(activityDefinitions.Count * 4),
                        "Number of activity rows");
            List <string> cellActivityNames = gridCells.Select(c =>
                                                               c.InnerText).Distinct().ToList();

            Assert.That(cellActivityNames, Is.EquivalentTo(activityDefinitions.Select(ad => ad.Name)),
                        "Activity row names");
        }
        protected void SetUpApplicationServices()
        {
            LoadTestCamperRequests();
            // Arrange - use constructor to create directory with 1 file.
            ILogger <ActivityDefinitionService> logger = Substitute.For <ILogger <ActivityDefinitionService> >();
            ActivityDefinitionService           activityDefinitionService = new ActivityDefinitionService(_applicationName, logger);
            // Create a couple copies of the default.
            List <string> expectedActivitySets = new List <string>
            {
                DefaultSetName,
                "AnotherSet",
                "OneMore"
            };
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                activityDefinitionService.GetActivityDefinition(DefaultSetName));

            _expectedActivitySets.Add(DefaultSetName, new List <ActivityDefinition>(activityDefinitions));
            foreach (string addSet in expectedActivitySets.Skip(1))
            {
                activityDefinitions.RemoveAt(0);
                string content = ActivityDefinition.WriteActivityDefinitionsToString(activityDefinitions, logger);
                File.WriteAllText($"{ApplicationDirectoryInfo.FullName}\\{addSet}.xml", content);
                _expectedActivitySets.Add(addSet, new List <ActivityDefinition>(activityDefinitions));
            }

            ISchedulerService preloadScheduler = new SchedulerService(_applicationName,
                                                                      Substitute.For <ILogger <SchedulerService> >());

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                activityDefinitions = activityDefinitionService.GetActivityDefinition(
                    DefaultSetName).ToList();
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                preloadScheduler.CreateSchedule(PrebuiltScheduleId,
                                                camperRequests, activityDefinitions);
            }

            _schedulerService = new SchedulerService(_applicationName,
                                                     Substitute.For <ILogger <SchedulerService> >());
            _activityDefinitionService = new ActivityDefinitionService(_applicationName, logger);
        }
        /// <summary>
        /// Create a camper with a set of requests.
        /// </summary>
        /// <param name="name">Text to create a camper name from</param>
        /// <param name="activityRequests">Set of activity requests</param>
        /// <param name="alternateActivity">An alternate activity</param>
        /// <returns></returns>
        private CamperRequests BuildCamper(string name,
                                           IEnumerable <ActivityDefinition> activityRequests,
                                           ActivityDefinition alternateActivity)
        {
            int rank      = 1;
            var theCamper = new Camper {
                FirstName = $"{name}", LastName = $"{name}"
            };
            var camperRequests = new CamperRequests
            {
                Camper           = theCamper,
                ActivityRequests = new List <ActivityRequest>(activityRequests
                                                              .Select(ar => new ActivityRequest {
                    Rank = rank++, Activity = ar
                })),
                AlternateActivity = alternateActivity
            };

            return(camperRequests);
        }
Exemple #16
0
        public List <ActivityDefinition> CreateSchedule(string scheduleId, List <CamperRequests> camperRequests,
                                                        List <ActivityDefinition> activityDefinitions)
        {
            List <CamperRequests> unscheduledCamperRequests = Scheduler.ScheduleActivities(camperRequests, activityDefinitions, _logger);

            if (unscheduledCamperRequests.Any())
            {
                // Put the unscheduled blocks into a special unscheduled activity
                ActivityDefinition unscheduledActivity = new ActivityDefinition
                {
                    Name            = UnscheduledActivityName,
                    MaximumCapacity = int.MaxValue,
                    OptimalCapacity = 0
                };
                unscheduledActivity.PreloadBlocks();
                foreach (Camper unscheduledCamper in unscheduledCamperRequests.Select(cr => cr.Camper))
                {
                    int[] blockIds = { 0, 1, 2, 3 };
                    foreach (int unscheduledBlockId in blockIds
                             .Except(unscheduledCamper.ScheduledBlocks.Select(b => b.TimeSlot)))
                    {
                        unscheduledActivity.TryAssignCamperToExistingActivityBlock(unscheduledCamper, false);
                    }
                }
                // Put unscheduled activity at the top of the grid
                activityDefinitions.Insert(0, unscheduledActivity);
            }

            // Generate the schedule ID from the date.
            _schedulesById[scheduleId] = activityDefinitions;

            // Generate the camper groups
            List <HashSet <Camper> > camperGroups = CamperRequests.GenerateCamperMateGroups(camperRequests);

            _camperGroupsByScheduleId[scheduleId] = camperGroups;

            UpdateSchedule(scheduleId, activityDefinitions, camperGroups);

            return(activityDefinitions);
        }
        public void ActivityScheduleGrid_StartDragOfCamper_PayloadUpdated()
        {
            // Arrange - run schedule with successful data set
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <CamperRequests> camperRequests;

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                string scheduleId = "MySchedule";
                _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }
            RenderedComponent <ActivityScheduleGrid> component =
                _host.AddComponent <ActivityScheduleGrid>();

            // Act - Start a drag on a camper activity cell
            List <HtmlNode> camperActivityCells = component.FindAll("td")
                                                  .Where(node => node.Attributes.AttributesWithName("class")
                                                         .Any(a => a.Value.Contains("activity-camper-cell"))).ToList();

            Assert.That(camperActivityCells, Has.Count.EqualTo(camperRequests.Count() * 4),
                        "Number of camper activity cells");
            camperActivityCells[0].TriggerEventAsync("ondragstart", new DragEventArgs());

            // Assert - Grid pay load is set.
            // The first cell should be archery block 0
            Assert.That(component.Instance.DragPayload.ActivityName,
                        Is.EqualTo("Archery"), "Drag payload activity name");
            Assert.That(component.Instance.DragPayload.TimeSlot,
                        Is.EqualTo(0), "Drag pay load time slot");
            Assert.That(component.Instance.DragPayload.CamperName,
                        Is.Not.Null, "Drag pay load camper name");
        }
Exemple #18
0
        public async Task CamperScheduleGrid_SelectCamper_CamperRowHilite()
        {
            // Arrange - run schedule with successful data set and load grid
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <ActivityDefinition> schedule;

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                string scheduleId = "MySchedule";
                schedule = _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }
            RenderedComponent <CamperScheduleGrid> component =
                _host.AddComponent <CamperScheduleGrid>();

            // Act - select a camper
            Camper selectedCamper = schedule.First().ScheduledBlocks.First()
                                    .AssignedCampers.First();
            HtmlNode nameCell = component.FindAll("button")
                                .First(node => node.InnerText.Equals(selectedCamper.FullName));
            await nameCell.ClickAsync();

            // Assert - load the row and verify it has the selected-camper class
            List <HtmlNode> selectedCamperRows = component.FindAll("tr")
                                                 .Where(node => node.Attributes.AttributesWithName("class")
                                                        .Any(a => a.Value.Contains("selected-camper"))).ToList();

            Assert.That(selectedCamperRows, Has.Count.EqualTo(1), "Selected camper rows");
            Assert.That(selectedCamperRows[0].Elements("td").First(n =>
                                                                   n.Attributes.Any(a => a.Name.Equals("data-name") && a.Value.Equals("FullName"))).InnerText,
                        Is.EqualTo(selectedCamper.FullName), "Camper row name");
        }
Exemple #19
0
        public void GenerateCamperMateGroups_ValidInput_GeneratesExpectedList()
        {
            // Arrange load the known good camper list
            List <CamperRequests> camperRequests = CamperRequests.ReadCamperRequests(GoodFileLocation,
                                                                                     ActivityDefinitionTests.DefaultActivityDefinitions, _logger);

            // Act - Generate the camper groups
            List <HashSet <Camper> > camperMateGroups = CamperRequests.GenerateCamperMateGroups(camperRequests);

            // Assert
            Assert.That(camperMateGroups, Is.Not.Null, "camperMateGroups");
            List <HashSet <Camper> > expectedCamperMateGroups = new List <HashSet <Camper> >
            {
                {
                    new HashSet <Camper> {
                        new Camper {
                            LastName = "A"
                        },
                        new Camper {
                            LastName = "S"
                        },
                        new Camper {
                            LastName = "E"
                        },
                        new Camper {
                            LastName = "O"
                        },
                        new Camper {
                            LastName = "X"
                        },
                        new Camper {
                            LastName = "AC"
                        },
                        new Camper {
                            LastName = "AM"
                        },
                        new Camper {
                            LastName = "AS"
                        },
                        new Camper {
                            LastName = "AX"
                        },
                        new Camper {
                            LastName = "BC"
                        },
                        new Camper {
                            LastName = "BF"
                        },
                        new Camper {
                            LastName = "BK"
                        },
                        new Camper {
                            LastName = "BN"
                        },
                        new Camper {
                            LastName = "CA"
                        },
                        new Camper {
                            LastName = "CH"
                        },
                        new Camper {
                            LastName = "CJ"
                        },
                        new Camper {
                            LastName = "CK"
                        },
                        new Camper {
                            LastName = "CR"
                        },
                        new Camper {
                            LastName = "D"
                        },
                        new Camper {
                            LastName = "R"
                        },
                        new Camper {
                            LastName = "AN"
                        },
                        new Camper {
                            LastName = "BG"
                        },
                        new Camper {
                            LastName = "CB"
                        },
                        new Camper {
                            LastName = "CL"
                        }
                    }
                },
                {
                    new HashSet <Camper> {
                        new Camper {
                            LastName = "B"
                        },
                        new Camper {
                            LastName = "U"
                        },
                        new Camper {
                            LastName = "V"
                        },
                        new Camper {
                            LastName = "Z"
                        },
                        new Camper {
                            LastName = "AA"
                        },
                        new Camper {
                            LastName = "AK"
                        },
                        new Camper {
                            LastName = "AT"
                        },
                        new Camper {
                            LastName = "BM"
                        },
                        new Camper {
                            LastName = "CG"
                        },
                        new Camper {
                            LastName = "CI"
                        }
                    }
                },
                {
                    new HashSet <Camper> {
                        new Camper {
                            LastName = "C"
                        },
                        new Camper {
                            LastName = "Y"
                        },
                        new Camper {
                            LastName = "T"
                        },
                        new Camper {
                            LastName = "AE"
                        },
                        new Camper {
                            LastName = "AH"
                        },
                        new Camper {
                            LastName = "AI"
                        },
                        new Camper {
                            LastName = "AR"
                        },
                        new Camper {
                            LastName = "AZ"
                        },
                        new Camper {
                            LastName = "BL"
                        },
                        new Camper {
                            LastName = "BR"
                        },
                        new Camper {
                            LastName = "CF"
                        }
                    }
                },
                {
                    new HashSet <Camper> {
                        new Camper {
                            LastName = "G"
                        },
                        new Camper {
                            LastName = "F"
                        },
                        new Camper {
                            LastName = "N"
                        },
                        new Camper {
                            LastName = "BD"
                        },
                        new Camper {
                            LastName = "BS"
                        },
                        new Camper {
                            LastName = "CC"
                        },
                        new Camper {
                            LastName = "CS"
                        },
                        new Camper {
                            LastName = "I"
                        }
                    }
                },
                {
                    new HashSet <Camper> {
                        new Camper {
                            LastName = "K"
                        },
                        new Camper {
                            LastName = "H"
                        },
                        new Camper {
                            LastName = "P"
                        },
                        new Camper {
                            LastName = "BE"
                        },
                        new Camper {
                            LastName = "BU"
                        }
                    }
                },
                {
                    new HashSet <Camper> {
                        new Camper {
                            LastName = "AB"
                        },
                        new Camper {
                            LastName = "W"
                        },
                        new Camper {
                            LastName = "AO"
                        },
                        new Camper {
                            LastName = "AP"
                        }
                    }
                }
            };

            Assert.That(camperMateGroups.Count, Is.EqualTo(expectedCamperMateGroups.Count),
                        "Number of camper mate groups");
            foreach (var expectedCamperMateGroup in expectedCamperMateGroups)
            {
                bool foundMatch = false;
                foreach (var actualCamperMateGroup in camperMateGroups)
                {
                    foundMatch = actualCamperMateGroup.SetEquals(expectedCamperMateGroup);
                    if (foundMatch)
                    {
                        break;
                    }
                }
                StringBuilder expectedCamperStringBuilder = new StringBuilder();
                foreach (Camper expectedCamper in expectedCamperMateGroup)
                {
                    if (expectedCamperStringBuilder.Length > 0)
                    {
                        expectedCamperStringBuilder.Append(',');
                    }
                    expectedCamperStringBuilder.Append(expectedCamper.LastName);
                }
                Assert.That(foundMatch, $"found match for {expectedCamperStringBuilder}");
            }
        }
        public void ActivityScheduleGrid_DropCamperInSameTimeSlot_CamperIsMoved()
        {
            // Arrange - run schedule with successful data set and start a drag
            List <ActivityDefinition> activityDefinitions = new List <ActivityDefinition>(
                _activityDefinitionService.GetActivityDefinition(DefaultSetName));
            List <CamperRequests> camperRequests;
            string scheduleId = "MySchedule";

            using (MemoryStream camperRequestStream = new MemoryStream(_validCamperRequestsBuffer))
            {
                camperRequests = CamperRequests.ReadCamperRequests(
                    camperRequestStream, activityDefinitions);
                _schedulerService.CreateSchedule(scheduleId, camperRequests, activityDefinitions);
                _localStorage.GetItemAsync <string>(Arg.Any <string>())
                .Returns(Task.FromResult(scheduleId));
            }
            RenderedComponent <ActivityScheduleGrid> component =
                _host.AddComponent <ActivityScheduleGrid>();
            List <HtmlNode> camperActivityCells = component.FindAll("td")
                                                  .Where(node => node.Attributes.AttributesWithName("class")
                                                         .Any(a => a.Value.Contains("activity-camper-cell"))).ToList();

            Assert.That(camperActivityCells, Has.Count.EqualTo(camperRequests.Count() * 4),
                        "Number of camper activity cells");
            // Gather up the activity block drop zones.
            List <HtmlNode> activityBlockCampers = component.FindAll("tr")
                                                   .Where(node => node.Attributes.AttributesWithName("ondrop").Any())
                                                   .ToList();

            Assert.That(activityBlockCampers, Has.Count.EqualTo(activityDefinitions.Count * 4),
                        "Number of activity rows");
            // Start a drag on a camper in the first activity block
            HtmlNode sourceCamperActivity = camperActivityCells.First(
                node => node.ParentNode.GetAttributeValue("id", "") ==
                activityBlockCampers[0].GetAttributeValue("id", "NotDefined"));

            sourceCamperActivity.TriggerEventAsync("ondragstart", new DragEventArgs());
            string camperName = component.Instance.DragPayload.CamperName;

            // Act - Drop on the block 0 for the next activity
            HtmlNode dropTarget = activityBlockCampers.First(n =>
                                                             n.GetAttributeValue("id", "")
                                                             .Equals($"{activityDefinitions[1].Name}-0"));

            dropTarget.TriggerEventAsync("ondrop", new DragEventArgs());

            // Assert - Grid pay load is reset.
            Assert.That(component.Instance.DragPayload.ActivityName, Is.EqualTo(null),
                        "Drag payload activity");
            Assert.That(component.Instance.DragPayload.CamperName, Is.EqualTo(null),
                        "Drag payload camper");
            Assert.That(component.Instance.DragPayload.TimeSlot, Is.EqualTo(0),
                        "Drag payload time slot");

            // Verify camper activities have not changed
            List <ActivityDefinition> schedule              = _schedulerService.GetSchedule(scheduleId);
            ActivityDefinition        sourceActivity        = schedule.Find(ad => ad.Name.Equals(activityDefinitions[0].Name));
            List <string>             assignedCampersByName = sourceActivity.ScheduledBlocks[component.Instance.DragPayload.TimeSlot]
                                                              .AssignedCampers.Select(c => c.FullName).ToList();

            Assert.That(assignedCampersByName, Has.None.EqualTo(camperName),
                        "Assigned campers on drag source");
            ActivityDefinition targetActivity = schedule.Find(ad => ad.Name.Equals(activityDefinitions[1].Name));

            assignedCampersByName = targetActivity.ScheduledBlocks[component.Instance.DragPayload.TimeSlot]
                                    .AssignedCampers.Select(c => c.FullName).ToList();
            Assert.That(assignedCampersByName, Has.One.EqualTo(camperName),
                        "Assigned campers on drop target");
        }
Exemple #21
0
        static void Main(string[] args)
        {
            var logger = new LoggerConverter(NLog.Web.NLogBuilder
                                             .ConfigureNLog("nlog.config")
                                             .GetCurrentClassLogger());

            Parser.Default.ParseArguments <Options>(args).WithParsed(opts =>
            {
                var activityDefinitions = ActivityDefinition.ReadActivityDefinitions(
                    opts.ActivityDefinitionsPath, logger);

                if (activityDefinitions == null)
                {
                    Environment.Exit(-2);
                }

                logger.LogInformation($"Found {activityDefinitions.Count} activity definitions in the file: {opts.ActivityDefinitionsPath}");

                var camperRequestsList = CamperRequests.ReadCamperRequests(opts.CamperRequestsPath,
                                                                           activityDefinitions, logger);

                if (camperRequestsList == null)
                {
                    Environment.Exit(-2);
                }

                logger.LogInformation($"Found {camperRequestsList.Count} campers in the file: {opts.CamperRequestsPath}");

                // Sort the campers by difficulty to resolve activity list.
                // Most difficult go first.
                camperRequestsList.Sort();

                // Preload the activity blocks
                foreach (var activity in activityDefinitions)
                {
                    activity.PreloadBlocks();
                }

                List <CamperRequests> unsuccessfulCamperRequests = Scheduler.ScheduleActivities(camperRequestsList,
                                                                                                opts.UseOptimalLimit, logger);
                if (opts.UseOptimalLimit && unsuccessfulCamperRequests.Any())
                {
                    logger.LogDebug($"Attempting to resolve {unsuccessfulCamperRequests.Count} " +
                                    $"unsuccessful camper requests using the activity maximum limits");
                    unsuccessfulCamperRequests = Scheduler.ScheduleActivities(unsuccessfulCamperRequests, false, logger);
                }
                foreach (var activity in activityDefinitions)
                {
                    foreach (var activityBlock in activity.ScheduledBlocks)
                    {
                        logger.LogDebug($"Scheduled '{activity.Name}' " +
                                        $"in block {activityBlock.TimeSlot} " +
                                        $"with {activityBlock.AssignedCampers.Count} campers");
                    }
                }

                if (!String.IsNullOrWhiteSpace(opts.ActivityScheduleCsvPath))
                {
                    ActivityDefinition.WriteScheduleToCsvFile(activityDefinitions, opts.ActivityScheduleCsvPath, logger);
                    logger.LogInformation($"Wrote the activity schedule file to '{opts.ActivityScheduleCsvPath}'");
                }

                if (!String.IsNullOrWhiteSpace(opts.CamperScheduleCsvPath))
                {
                    Camper.WriteScheduleToCsvFile(camperRequestsList.Select(cr => cr.Camper), opts.CamperScheduleCsvPath, logger);
                    logger.LogInformation($"Wrote the camper schedule file to '{opts.CamperScheduleCsvPath}'");
                }

                Console.Out.WriteLine();
                foreach (var unhappyCamper in unsuccessfulCamperRequests)
                {
                    List <ActivityRequest> unscheduledActivities = unhappyCamper.UnscheduledActivities;
                    if (unscheduledActivities.Any(ar => ar.Rank < 3))
                    {
                        logger.LogInformation($"Failed to place {unhappyCamper.Camper} in {String.Join(',', unscheduledActivities.Select(ar => ar?.ToString()))} ");
                    }
                    else
                    {
                        logger.LogInformation($"Failed to place {unhappyCamper.Camper} in " +
                                              $"{String.Join(',', unscheduledActivities.Select(ar => ar?.ToString()))} " +
                                              $"or alternate '{unhappyCamper.AlternateActivity?.Name}'");
                    }
                }

                if (unsuccessfulCamperRequests.Count == 0)
                {
                    logger.LogInformation($"Successfully scheduled {camperRequestsList.Count} " +
                                          $"campers into {activityDefinitions.Count} activities");
                    Environment.Exit(0);
                }
                else
                {
                    logger.LogInformation($"Failed to schedule {unsuccessfulCamperRequests.Count} " +
                                          $"of {camperRequestsList.Count} campers into " +
                                          $"{activityDefinitions.Count} activities");
                    Environment.Exit(-4);
                }
            }).WithNotParsed(opts =>
            {
                Environment.Exit(-1);
            });
        }